Improve MUC message and presence listeners

instead of using a PacketListener, which means that the user has to
downcast the Packet to Message, we now use a Listener which callback
parameter is already Message/Presence.

It is necessary to introduce MessageListener and PresenceListener, which
are interfaces that have a callback for Message/Presence instead of
Packet. The 'old' MessageListener is renamed to ChatMessageListener.

Use Generics in ConnectionDetachedPacketCollector.
This commit is contained in:
Florian Schmaus 2014-10-12 18:01:19 +02:00
parent 38582eed84
commit e835df5641
13 changed files with 178 additions and 65 deletions

View File

@ -40,7 +40,7 @@ public class Chat {
private ChatManager chatManager; private ChatManager chatManager;
private String threadID; private String threadID;
private String participant; private String participant;
private final Set<MessageListener> listeners = new CopyOnWriteArraySet<MessageListener>(); private final Set<ChatMessageListener> listeners = new CopyOnWriteArraySet<ChatMessageListener>();
/** /**
* Creates a new chat with the specified user and thread ID. * Creates a new chat with the specified user and thread ID.
@ -118,7 +118,7 @@ public class Chat {
* *
* @param listener a packet listener. * @param listener a packet listener.
*/ */
public void addMessageListener(MessageListener listener) { public void addMessageListener(ChatMessageListener listener) {
if(listener == null) { if(listener == null) {
return; return;
} }
@ -126,7 +126,7 @@ public class Chat {
listeners.add(listener); listeners.add(listener);
} }
public void removeMessageListener(MessageListener listener) { public void removeMessageListener(ChatMessageListener listener) {
listeners.remove(listener); listeners.remove(listener);
} }
@ -145,7 +145,7 @@ public class Chat {
* *
* @return an unmodifiable collection of all of the listeners registered with this chat. * @return an unmodifiable collection of all of the listeners registered with this chat.
*/ */
public Collection<MessageListener> getListeners() { public Collection<ChatMessageListener> getListeners() {
return Collections.unmodifiableCollection(listeners); return Collections.unmodifiableCollection(listeners);
} }
@ -174,7 +174,7 @@ public class Chat {
// probably never had one. // probably never had one.
message.setThread(threadID); message.setThread(threadID);
for (MessageListener listener : listeners) { for (ChatMessageListener listener : listeners) {
listener.processMessage(this, message); listener.processMessage(this, message);
} }
} }

View File

@ -206,7 +206,7 @@ public class ChatManager extends Manager{
* @param listener the listener which will listen for new messages from this chat. * @param listener the listener which will listen for new messages from this chat.
* @return the created chat. * @return the created chat.
*/ */
public Chat createChat(String userJID, MessageListener listener) { public Chat createChat(String userJID, ChatMessageListener listener) {
return createChat(userJID, null, listener); return createChat(userJID, null, listener);
} }
@ -218,7 +218,7 @@ public class ChatManager extends Manager{
* @param listener the listener to add to the chat * @param listener the listener to add to the chat
* @return the created chat. * @return the created chat.
*/ */
public Chat createChat(String userJID, String thread, MessageListener listener) { public Chat createChat(String userJID, String thread, ChatMessageListener listener) {
if (thread == null) { if (thread == null) {
thread = nextID(); thread = nextID();
} }

View File

@ -0,0 +1,27 @@
/**
*
* Copyright 2003-2007 Jive Software.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack;
import org.jivesoftware.smack.packet.Message;
/**
*
*/
public interface ChatMessageListener {
void processMessage(Chat chat, Message message);
}

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2003-2007 Jive Software. * Copyright © 2014 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,5 +23,5 @@ import org.jivesoftware.smack.packet.Message;
* *
*/ */
public interface MessageListener { public interface MessageListener {
void processMessage(Chat chat, Message message); void processMessage(Message message);
} }

View File

@ -0,0 +1,27 @@
/**
*
* Copyright © 2014 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack;
import org.jivesoftware.smack.packet.Presence;
/**
*
*/
public interface PresenceListener {
void processPresence(Presence presence);
}

View File

@ -0,0 +1,39 @@
/**
*
* Copyright © 2014 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.filter;
import org.jivesoftware.smack.packet.Message;
/**
* Filters message stanzas which have at least one body
*/
public class MessageWithSubjectFilter extends FlexiblePacketTypeFilter<Message> {
public static final PacketFilter INSTANCE = new MessageWithSubjectFilter();
private MessageWithSubjectFilter() {
super(Message.class);
}
@Override
protected boolean acceptSpecific(Message message) {
// Accept only messages which have a subject set
return message.getSubject() != null;
}
}

View File

@ -386,7 +386,7 @@ public class ChatConnectionTest {
class TestChatManagerListener implements ChatManagerListener { class TestChatManagerListener implements ChatManagerListener {
private Chat newChat; private Chat newChat;
private MessageListener listener; private ChatMessageListener listener;
public TestChatManagerListener(TestMessageListener msgListener) { public TestChatManagerListener(TestMessageListener msgListener) {
listener = msgListener; listener = msgListener;
@ -423,7 +423,7 @@ public class ChatConnectionTest {
} }
} }
private class TestMessageListener implements MessageListener { private class TestMessageListener implements ChatMessageListener {
private Chat msgChat; private Chat msgChat;
private int counter = 0; private int counter = 0;

View File

@ -18,14 +18,14 @@
package org.jivesoftware.smackx.chatstates; package org.jivesoftware.smackx.chatstates;
import org.jivesoftware.smack.Chat; import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.MessageListener; import org.jivesoftware.smack.ChatMessageListener;
/** /**
* Events for when the state of a user in a chat changes. * Events for when the state of a user in a chat changes.
* *
* @author Alexander Wenckus * @author Alexander Wenckus
*/ */
public interface ChatStateListener extends MessageListener { public interface ChatStateListener extends ChatMessageListener {
/** /**
* Fired when the state of a chat with another user changes. * Fired when the state of a chat with another user changes.

View File

@ -23,10 +23,10 @@ import java.util.WeakHashMap;
import org.jivesoftware.smack.Chat; import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager; import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ChatManagerListener; import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.ChatMessageListener;
import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.PacketInterceptor; import org.jivesoftware.smack.PacketInterceptor;
import org.jivesoftware.smack.filter.NotFilter; import org.jivesoftware.smack.filter.NotFilter;
import org.jivesoftware.smack.filter.PacketExtensionFilter; import org.jivesoftware.smack.filter.PacketExtensionFilter;
@ -143,7 +143,7 @@ public class ChatStateManager extends Manager {
} }
private void fireNewChatState(Chat chat, ChatState state) { private void fireNewChatState(Chat chat, ChatState state) {
for (MessageListener listener : chat.getListeners()) { for (ChatMessageListener listener : chat.getListeners()) {
if (listener instanceof ChatStateListener) { if (listener instanceof ChatStateListener) {
((ChatStateListener) listener).stateChanged(chat, state); ((ChatStateListener) listener).stateChanged(chat, state);
} }
@ -164,7 +164,7 @@ public class ChatStateManager extends Manager {
} }
} }
private class IncomingMessageInterceptor implements ChatManagerListener, MessageListener { private class IncomingMessageInterceptor implements ChatManagerListener, ChatMessageListener {
public void chatCreated(final Chat chat, boolean createdLocally) { public void chatCreated(final Chat chat, boolean createdLocally) {
chat.addMessageListener(this); chat.addMessageListener(this);

View File

@ -31,8 +31,8 @@ import org.jivesoftware.smack.packet.Packet;
* *
* @author Larry Kirschner * @author Larry Kirschner
*/ */
class ConnectionDetachedPacketCollector { class ConnectionDetachedPacketCollector<P extends Packet> {
private ArrayBlockingQueue<Packet> resultQueue; private ArrayBlockingQueue<P> resultQueue;
/** /**
* Creates a new packet collector. If the packet filter is <tt>null</tt>, then * Creates a new packet collector. If the packet filter is <tt>null</tt>, then
@ -47,7 +47,7 @@ class ConnectionDetachedPacketCollector {
* all packets will match this collector. * all packets will match this collector.
*/ */
public ConnectionDetachedPacketCollector(int maxSize) { public ConnectionDetachedPacketCollector(int maxSize) {
this.resultQueue = new ArrayBlockingQueue<Packet>(maxSize); this.resultQueue = new ArrayBlockingQueue<P>(maxSize);
} }
/** /**
@ -58,7 +58,7 @@ class ConnectionDetachedPacketCollector {
* @return the next packet result, or <tt>null</tt> if there are no more * @return the next packet result, or <tt>null</tt> if there are no more
* results. * results.
*/ */
public Packet pollResult() { public P pollResult() {
return resultQueue.poll(); return resultQueue.poll();
} }
@ -68,7 +68,7 @@ class ConnectionDetachedPacketCollector {
* *
* @return the next available packet. * @return the next available packet.
*/ */
public Packet nextResult() { public P nextResult() {
try { try {
return resultQueue.take(); return resultQueue.take();
} }
@ -85,7 +85,7 @@ class ConnectionDetachedPacketCollector {
* @param timeout the amount of time to wait for the next packet (in milleseconds). * @param timeout the amount of time to wait for the next packet (in milleseconds).
* @return the next available packet. * @return the next available packet.
*/ */
public Packet nextResult(long timeout) { public P nextResult(long timeout) {
try { try {
return resultQueue.poll(timeout, TimeUnit.MILLISECONDS); return resultQueue.poll(timeout, TimeUnit.MILLISECONDS);
} }
@ -100,7 +100,7 @@ class ConnectionDetachedPacketCollector {
* *
* @param packet the packet to process. * @param packet the packet to process.
*/ */
protected void processPacket(Packet packet) { protected void processPacket(P packet) {
if (packet == null) { if (packet == null) {
return; return;
} }

View File

@ -35,12 +35,14 @@ import java.util.logging.Logger;
import org.jivesoftware.smack.Chat; import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager; import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ChatMessageListener;
import org.jivesoftware.smack.ConnectionCreationListener; import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.MessageListener; import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.PacketCollector; import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.PacketInterceptor; import org.jivesoftware.smack.PacketInterceptor;
import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.PresenceListener;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackException.NotConnectedException;
@ -107,13 +109,16 @@ public class MultiUserChat {
new ArrayList<UserStatusListener>(); new ArrayList<UserStatusListener>();
private final List<ParticipantStatusListener> participantStatusListeners = private final List<ParticipantStatusListener> participantStatusListeners =
new ArrayList<ParticipantStatusListener>(); new ArrayList<ParticipantStatusListener>();
private final Set<MessageListener> messageListeners = new CopyOnWriteArraySet<MessageListener>();
private final Set<PresenceListener> presenceListeners = new CopyOnWriteArraySet<PresenceListener>();
private final PacketFilter fromRoomFilter;
private final PacketListener messageListener;
private final PacketListener presenceListener;
private PacketFilter presenceFilter;
private List<PacketInterceptor> presenceInterceptors = new ArrayList<PacketInterceptor>(); private List<PacketInterceptor> presenceInterceptors = new ArrayList<PacketInterceptor>();
private PacketFilter messageFilter;
private RoomListenerMultiplexor roomListenerMultiplexor; private RoomListenerMultiplexor roomListenerMultiplexor;
private ConnectionDetachedPacketCollector messageCollector; private ConnectionDetachedPacketCollector<Message> messageCollector;
private List<PacketListener> connectionListeners = new ArrayList<PacketListener>();
static { static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@ -174,6 +179,27 @@ public class MultiUserChat {
public MultiUserChat(XMPPConnection connection, String room) { public MultiUserChat(XMPPConnection connection, String room) {
this.connection = connection; this.connection = connection;
this.room = room.toLowerCase(Locale.US); this.room = room.toLowerCase(Locale.US);
messageListener = new PacketListener() {
@Override
public void processPacket(Packet packet) throws NotConnectedException {
Message message = (Message) packet;
for (MessageListener listener : messageListeners) {
listener.processMessage(message);
}
}
};
presenceListener = new PacketListener() {
@Override
public void processPacket(Packet packet) throws NotConnectedException {
Presence presence = (Presence) packet;
for (PresenceListener listener : presenceListeners) {
listener.processPresence(presence);
}
}
};
fromRoomFilter = FromMatchesFilter.create(room);
init(); init();
} }
@ -349,6 +375,11 @@ public class MultiUserChat {
this.nickname = nickname; this.nickname = nickname;
joined = true; joined = true;
// Setup the messageListeners and presenceListeners
connection.addPacketListener(messageListener, new AndFilter(fromRoomFilter,
MessageTypeFilter.GROUPCHAT));
connection.addPacketListener(presenceListener, new AndFilter(fromRoomFilter,
PacketTypeFilter.PRESENCE));
// Update the list of joined rooms through this connection // Update the list of joined rooms through this connection
List<String> rooms = joinedRooms.get(connection); List<String> rooms = joinedRooms.get(connection);
if (rooms == null) { if (rooms == null) {
@ -1499,22 +1530,22 @@ public class MultiUserChat {
* *
* @param listener a packet listener that will be notified of any presence packets * @param listener a packet listener that will be notified of any presence packets
* sent to the group chat. * sent to the group chat.
* @return true if the listener was not already added.
*/ */
public void addParticipantListener(PacketListener listener) { public boolean addParticipantListener(PresenceListener listener) {
connection.addPacketListener(listener, presenceFilter); return presenceListeners.add(listener);
connectionListeners.add(listener);
} }
/** /**
* Remoces a packet listener that was being notified of any new Presence packets * Removes a packet listener that was being notified of any new Presence packets
* sent to the group chat. * sent to the group chat.
* *
* @param listener a packet listener that was being notified of any presence packets * @param listener a packet listener that was being notified of any presence packets
* sent to the group chat. * sent to the group chat.
* @return true if the listener was removed, otherwise the listener was not added previously.
*/ */
public void removeParticipantListener(PacketListener listener) { public boolean removeParticipantListener(PresenceListener listener) {
connection.removePacketListener(listener); return presenceListeners.remove(listener);
connectionListeners.remove(listener);
} }
/** /**
@ -1668,7 +1699,7 @@ public class MultiUserChat {
* created chat. * created chat.
* @return new Chat for sending private messages to a given room occupant. * @return new Chat for sending private messages to a given room occupant.
*/ */
public Chat createPrivateChat(String occupant, MessageListener listener) { public Chat createPrivateChat(String occupant, ChatMessageListener listener) {
return ChatManager.getInstanceFor(connection).createChat(occupant, listener); return ChatManager.getInstanceFor(connection).createChat(occupant, listener);
} }
@ -1704,7 +1735,7 @@ public class MultiUserChat {
* <tt>null</tt> otherwise. * <tt>null</tt> otherwise.
*/ */
public Message pollMessage() { public Message pollMessage() {
return (Message) messageCollector.pollResult(); return messageCollector.pollResult();
} }
/** /**
@ -1714,7 +1745,7 @@ public class MultiUserChat {
* @return the next message. * @return the next message.
*/ */
public Message nextMessage() { public Message nextMessage() {
return (Message) messageCollector.nextResult(); return messageCollector.nextResult();
} }
/** /**
@ -1727,7 +1758,7 @@ public class MultiUserChat {
* message becoming available. * message becoming available.
*/ */
public Message nextMessage(long timeout) { public Message nextMessage(long timeout) {
return (Message) messageCollector.nextResult(timeout); return messageCollector.nextResult(timeout);
} }
/** /**
@ -1739,10 +1770,10 @@ public class MultiUserChat {
* PacketListener. * PacketListener.
* *
* @param listener a packet listener. * @param listener a packet listener.
* @return true if the listener was not already added.
*/ */
public void addMessageListener(PacketListener listener) { public boolean addMessageListener(MessageListener listener) {
connection.addPacketListener(listener, messageFilter); return messageListeners.add(listener);
connectionListeners.add(listener);
} }
/** /**
@ -1751,10 +1782,10 @@ public class MultiUserChat {
* being delivered to the listener. * being delivered to the listener.
* *
* @param listener a packet listener. * @param listener a packet listener.
* @return true if the listener was removed, otherwise the listener was not added previously.
*/ */
public void removeMessageListener(PacketListener listener) { public boolean removeMessageListener(MessageListener listener) {
connection.removePacketListener(listener); return messageListeners.remove(listener);
connectionListeners.remove(listener);
} }
/** /**
@ -1798,6 +1829,8 @@ public class MultiUserChat {
if (rooms == null) { if (rooms == null) {
return; return;
} }
connection.removePacketListener(messageListener);
connection.removePacketListener(presenceListener);
rooms.remove(room); rooms.remove(room);
cleanup(); cleanup();
} }
@ -1906,12 +1939,8 @@ public class MultiUserChat {
} }
private void init() { private void init() {
// Create filters
messageFilter = new AndFilter(FromMatchesFilter.create(room), MessageTypeFilter.GROUPCHAT);
presenceFilter = new AndFilter(FromMatchesFilter.create(room), PacketTypeFilter.PRESENCE);
// Create a collector for incoming messages. // Create a collector for incoming messages.
messageCollector = new ConnectionDetachedPacketCollector(); messageCollector = new ConnectionDetachedPacketCollector<Message>();
// Create a listener for subject updates. // Create a listener for subject updates.
PacketListener subjectListener = new PacketListener() { PacketListener subjectListener = new PacketListener() {
@ -2324,10 +2353,6 @@ public class MultiUserChat {
try { try {
if (connection != null) { if (connection != null) {
roomListenerMultiplexor.removeRoom(room); roomListenerMultiplexor.removeRoom(room);
// Remove all the PacketListeners added to the connection by this chat
for (PacketListener connectionListener : connectionListeners) {
connection.removePacketListener(connectionListener);
}
} }
} catch (Exception e) { } catch (Exception e) {
// Do nothing // Do nothing

View File

@ -20,6 +20,7 @@ package org.jivesoftware.smackx.muc;
import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.filter.MessageTypeFilter; import org.jivesoftware.smack.filter.MessageTypeFilter;
import org.jivesoftware.smack.filter.MessageWithSubjectFilter;
import org.jivesoftware.smack.filter.PacketExtensionFilter; import org.jivesoftware.smack.filter.PacketExtensionFilter;
import org.jivesoftware.smack.filter.PacketFilter; import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter; import org.jivesoftware.smack.filter.PacketTypeFilter;
@ -37,22 +38,16 @@ import org.jivesoftware.smackx.muc.packet.MUCUser;
class PacketMultiplexListener implements PacketListener { class PacketMultiplexListener implements PacketListener {
private static final PacketFilter PRESENCE_FILTER = new PacketTypeFilter(Presence.class); private static final PacketFilter PRESENCE_FILTER = new PacketTypeFilter(Presence.class);
private static final PacketFilter SUBJECT_FILTER = new PacketFilter() {
public boolean accept(Packet packet) {
Message msg = (Message) packet;
return msg.getSubject() != null;
}
};
private static final PacketFilter DECLINES_FILTER = new PacketExtensionFilter(MUCUser.ELEMENT, private static final PacketFilter DECLINES_FILTER = new PacketExtensionFilter(MUCUser.ELEMENT,
MUCUser.NAMESPACE); MUCUser.NAMESPACE);
private ConnectionDetachedPacketCollector messageCollector; private ConnectionDetachedPacketCollector<Message> messageCollector;
private PacketListener presenceListener; private PacketListener presenceListener;
private PacketListener subjectListener; private PacketListener subjectListener;
private PacketListener declinesListener; private PacketListener declinesListener;
public PacketMultiplexListener( public PacketMultiplexListener(
ConnectionDetachedPacketCollector messageCollector, ConnectionDetachedPacketCollector<Message> messageCollector,
PacketListener presenceListener, PacketListener presenceListener,
PacketListener subjectListener, PacketListener declinesListener) { PacketListener subjectListener, PacketListener declinesListener) {
if (messageCollector == null) { if (messageCollector == null) {
@ -78,9 +73,9 @@ class PacketMultiplexListener implements PacketListener {
presenceListener.processPacket(p); presenceListener.processPacket(p);
} }
else if (MessageTypeFilter.GROUPCHAT.accept(p)) { else if (MessageTypeFilter.GROUPCHAT.accept(p)) {
messageCollector.processPacket(p); messageCollector.processPacket((Message) p);
if (SUBJECT_FILTER.accept(p)) { if (MessageWithSubjectFilter.INSTANCE.accept(p)) {
subjectListener.processPacket(p); subjectListener.processPacket(p);
} }
} }

View File

@ -28,7 +28,7 @@ public class ConnectionDetachedPacketCollectorTest
@Test @Test
public void verifyRollover() public void verifyRollover()
{ {
ConnectionDetachedPacketCollector collector = new ConnectionDetachedPacketCollector(5); ConnectionDetachedPacketCollector<Packet> collector = new ConnectionDetachedPacketCollector<Packet>(5);
for (int i=0; i<6; i++) for (int i=0; i<6; i++)
{ {
@ -68,7 +68,7 @@ public class ConnectionDetachedPacketCollectorTest
public void verifyThreadSafety() public void verifyThreadSafety()
{ {
int insertCount = 500; int insertCount = 500;
final ConnectionDetachedPacketCollector collector = new ConnectionDetachedPacketCollector(insertCount); final ConnectionDetachedPacketCollector<Packet> collector = new ConnectionDetachedPacketCollector<Packet>(insertCount);
Thread consumer1 = new Thread(new Runnable() Thread consumer1 = new Thread(new Runnable()
{ {