I have a simple program to generate inputs to CRC32 which output a number ending with 123456 (in hex). It does bruteforce in a worker thread (the next step would be to make multiple worker threads). The worker thread sends results to the queue q
.
import java.util.*;
import java.util.concurrent.*;
import java.util.zip.*;
class A {
static final BlockingQueue<List<Byte>> q =
new LinkedBlockingQueue<List<Byte>>();
static {
new Thread() {
public void run() {
System.out.println("worker thread starting");
int len = 1;
byte[] a = new byte[32];
for (int i =0; i < 32; i++) a[i]=-128;
while (true) {
CRC32 crc = new CRC32();
crc.update(a, 0, len);
long x = crc.getValue();
if ((x & 0xffffff) == 0x123456) {
System.out.println("HA " + Arrays.toString(a) + "; " + x);
List<Byte> l = new LinkedList<Byte>();
for (int i = 0; i < a.length; i++) l.add(a[i]);
System.out.println("A");
q.add(l);
System.out.println("B"); // never reaches here
}
// generate next guess
boolean c = true;
for (int i = 0; i < len && c; i++) {
c = ++a[i] == -128;
if (c) if (i + 2 > len) len = i + 2;
}
}
}
}.start();
}
// for stats: amount of inputs found per interval
static long amount = 3;
static long interval;
static {
// record an initial value for interval, so any code using
// it doesn't have to have a special case to check whether
// it's initialized
long start = System.currentTimeMillis();
while (q.size() != amount);
interval = System.currentTimeMillis() - start;
}
public static void main(String[] args) {
System.out.println("main");
}
}
For some reason, it gets stuck:
$ javac A.java && java A
worker thread starting
HA [-49, 72, 73, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128]; 1376924758
A
The worker thread is clearly blocked in sending to the queue (q.add(l)
), otherwise, "B" would be printed to the console. If I comment out the line reading from the queue (while (q.size() != amount)
), it no longer gets stuck. I thought this behavior is impossible for an unbounded queue (assuming there aren't already 2147483647 elements in it). This is not a SynchronousQueue
, so sending to the queue should work regardless of whether any thread is receiving from it. In fact, this behavior seems opposite to SynchronousQueue
: sending only works if there is no receiver.
Why is the worker thread being blocked when it tries to send to the queue?