Gangmax Blog

Java SynchronousQueue

Synchronous queues are similar to rendezvous channels used in CSP and Ada. They are well suited for handoff designs, in which an object running in one thread must sync up with an object running in another thread in order to hand it some information, event, or task. –From Java offical document here

From my perspective, it’s useful when passing data from one thread to another and there is a need to make the consumer thread wait until the data made by the producer thread is ready.

The following code example shows how to use it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class SynchronousDemo {

public static void main(String[] args) throws InterruptedException {
final SynchronousQueue<String> synchronousQueue = new SynchronousQueue<String>();
Thread thread1 = new Thread(){
@Override
public void run() {
try {
System.out.println("Thread 1 is taking: " + synchronousQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread2 = new Thread(){
@Override
public void run() {
try {
System.out.println("Thread 2 is taking: " + synchronousQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread1.start();
thread2.start();
Thread.sleep(5000);
System.out.println(synchronousQueue.offer("hello 1"));
Thread.sleep(5000);
System.out.println(synchronousQueue.offer("hello 2"));
}
}

The above code gets the following output:

1
2
3
4
5
6
true
Thread 2 is taking: hello 1
true
Thread 1 is taking: hello 2

Process finished with exit code 0

Note the order of the output is NOT the same as the order of the threads starting. If you want the same output order as the threads starting, change the “fair” argument of the constructor method of SynchronousQueue class, as below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class SynchronousDemo {

public static void main(String[] args) throws InterruptedException {
final SynchronousQueue<String> synchronousQueue = new SynchronousQueue<String>(true);
Thread thread1 = new Thread(){
@Override
public void run() {
try {
System.out.println("Thread 1 is taking: " + synchronousQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread2 = new Thread(){
@Override
public void run() {
try {
System.out.println("Thread 2 is taking: " + synchronousQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread1.start();
thread2.start();
Thread.sleep(5000);
System.out.println(synchronousQueue.offer("hello 1"));
Thread.sleep(5000);
System.out.println(synchronousQueue.offer("hello 2"));
}
}

The above code gets the following output:

1
2
3
4
5
6
true
Thread 1 is taking: hello 1
true
Thread 2 is taking: hello 2

Process finished with exit code 0

This post has more useful details about Java concurrent.

Comments