工作中需要实现阻塞等待的功能,所以研究了一下BlockingQueue接口的两个实现LinkedBlockingQueue和SynchronousQueue。
LinkedBlockingQueue是具备存储功能的阻塞列表,通过两个方法来完成阻塞等待功能,代码如下:
private static LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();
public static void testLinkedBlockingQueue() {
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
System.out.println("读取数据:" + queue.take());
Thread.sleep(1500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}, "打印线程").start();
new Thread(new Runnable() {
int i = 1;
@Override
public void run() {
while (true) {
try {
String v = String.valueOf(i++);
System.out.println("写入数据:" + v + (queue.offer(v)?"成功":"失败"));
//queue.put(v);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}, "更新线程").start();
}
通过调用该静态方法,打印效果如下:
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="plain">写入数据:1成功
读取数据:1
写入数据:2成功
读取数据:2
写入数据:3成功
写入数据:4成功
读取数据:3
写入数据:5成功
读取数据:4
写入数据:6成功
读取数据:5
写入数据:7成功
写入数据:8成功
读取数据:6
写入数据:9成功
写入数据:10成功
读取数据:7
写入数据:11成功
说明没有阻塞的存储方法offer成功的将数据存储到了列表中,并且列表读取时,会按照顺序从头读取。
接下来看一下SynchronousQueue,该同步队列几乎是没有存储空间的的,也就是说,只有读取函数在阻塞状态时,写入才会有效,看一下下面的测试代码:
private static BlockingQueue<String> synchronousQueue = new SynchronousQueue<String>();
public static void testSynchronousQueue() {
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
System.out.println("读取数据:" + synchronousQueue.take());
Thread.sleep(1500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}, "打印线程").start();
new Thread(new Runnable() {
int i = 1;
@Override
public void run() {
while (true) {
try {
String v = String.valueOf(i++);
System.out.println("写入数据:" + v + (synchronousQueue.offer(v)?"成功":"失败"));
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}, "更新线程").start();
}
测试打印信息如下
写入数据:1失败
写入数据:2成功
读取数据:2
写入数据:3失败
写入数据:4成功
读取数据:4
写入数据:5失败
写入数据:6成功
读取数据:6
写入数据:7失败
写入数据:8成功
读取数据:8
写入数据:9失败
写入数据:10成功
读取数据:10
写入数据:11失败
写入数据:12成功
读取数据:12
写入数据:13失败
测试结果也验证了上述推论。
两种实现类各有特点,适合不同的应用环境,避免了自己通过wait()和notify()来实现同步。