I am suspecting that using a blocking queue is blocking so much that it is causing the slowdown.
You suspect wrong. The following test program pushes 1 million Integers through an ArrayBlockingQueue:
public class ArrayBlockingQueuePerfTest {
int maxi = 1000000;
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1000,
true);
Thread sender = new Thread("sender") {
public void run() {
try {
for (int i = 0; i < maxi; i++) {
queue.offer(i, 1, TimeUnit.SECONDS);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
};
};
Thread receiver = new Thread("receiver") {
public void run() {
try {
int count = 0;
long sum = 0;
while (count < maxi) {
sum += queue.poll(1, TimeUnit.SECONDS);
count++;
}
System.out.println("done");
System.out.println("expected sum: " + ((long) maxi) * (maxi - 1) / 2);
System.out.println("actual sum: " + sum);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
};
};
public ArrayBlockingQueuePerfTest() {
sender.start();
receiver.start();
}
public static void main(String[] args) {
new ArrayBlockingQueuePerfTest();
}
}
On my laptop, it terminates in a couple seconds. So wherever your performance bottleneck is, it is not the ArrayBlockingQueue, which could handle a throughput at least 3 orders of magnitude higher than you need. Put differently, even if you found a thread communication approach that takes no execution time at all, that would only speed up your program by at most 0.1%.
Take home lesson for this and all other performance problems: The first step when tackling any performance problem in existing code is to measure which part of the code is slow, as usually, it is not where one expects. Profilers simplify this task greatly.