Context:
As I understand, BlockingQueue is used to pass data between threads aka producer-consumer problem. For example, in my case I use it to store received DatagramPackets so that other thread can process them. For now it just logs all incoming packets to a log file. Here is the code I used to imitate the process:
Cons c = new Cons();
new Thread(c).start();
int i = 0;
byte[] databuf = new byte[1024];
DatagramPacket packet = new DatagramPacket(databuf, databuf.length);
try (DatagramSocket socket = new DatagramSocket(5555)){
while (10 < System.currentTimeMillis()) {
socket.receive(packet);
c.add(packet);
socket.send(new DatagramPacket("OK".getBytes(), "OK".getBytes().length, packet.getAddress(),
packet.getPort()));
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
Cons class handles writing to BlockingQueue and logging it in separate threads :
private static class Cons implements Runnable {
LinkedBlockingQueue<DatagramPacket> q = new LinkedBlockingQueue<>();
@Override
public void run() {
while (10 < System.currentTimeMillis()) {
try {
DatagramPacket packet = q.take();
logger.log(Level.INFO, "!" +"Message:" + new String(packet.getData(), packet.getOffset(),
packet.getLength()));
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void add(DatagramPacket p) throws InterruptedException {
q.put(p);
}
Client side just sends set number of packets that this server receives.
Problem:
If thread that does reading from queue is somehow delayed, it starts to skip elements. In code example above it's imitated with Thread.sleep() but even logging alone is enough to make it skip few elements occasionally. And longer it takes for thread to request next element in queue more elements it skips. Using drainTo() provides same result.
In short, it rather behaives like single-element variable and not as queue. I don't understand why doesn't it just store all elements added so that handling thread can take them one-by-one and read?
Question:
Am I doing something wrong or is such behaviour intended?
Although now that I think about it, if even logging alone makes it so handler can't keep up with queue growing, how do I implement processing packets from multiple users? Do I have to create a different thread for each packet? That doesn't quite seems rational.