对于许多多线程的问题,其实是可以通过使用一个或多个队列以安全的方式将其形式化的,即使用队列可以安全的从一个线程
向另一个线程传输数据。其中阻塞队列就是一种很有用的工具,工作者线程可以周期性的将中间结果存储在阻塞队列中,而其他工作者
线程则可以移出中间结果并进行加以修改,而且在其运行的同时队列还会自动的平衡负载。
-----------YYC
本部分则以用阻塞队列的方式解决生产者和消费者问题来作为具体实例进行说明。生产者线程向队列中插入元素,消费者线程
则从中取出它们,特别是当试图向队列中添加元素而队列已满,或者想从队列中移出元素而队列为空的时候,阻塞队列则会导致当前的
这个队列阻塞。
For Example:
//先定义生产者和消费者类
class Producer implements Runnable {
private final BlockingQueue sharedQueue;
public Producer(BlockingQueue sharedQueue) {
this.sharedQueue = sharedQueue;
}
@Override
public void run() {
for(int i=0; i<10; i++){
try {
System.out.println("Produced: " + i);
sharedQueue.put(i);
//如果该队列已满则会自动阻塞该线程
//如果该线程在阻塞的过程中被中断则会发生中断异常
} catch (InterruptedException ex) {
Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
class Consumer implements Runnable{
private final BlockingQueue sharedQueue;
public Consumer (BlockingQueue sharedQueue) {
this.sharedQueue = sharedQueue;
}
@Override
public void run() {
while(true){
try {
System.out.println("Consumed: "+ sharedQueue.take());
//如果该阻塞队列为空则会自动阻塞该线程
} catch (InterruptedException ex) {
Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
break;
}
}
}
}
//调用过程
case R.id.button3://阻塞队列实现生产者和消费者模式
BlockingQueue sharedQueue = new LinkedBlockingQueue();//容量没有上界的阻塞队列
Thread prodThread = new Thread(new Producer(sharedQueue));
Thread consThread = new Thread(new Consumer(sharedQueue));
prodThread.start();
consThread.start();
break;
在JAVA的concurrent包中其实是提供了阻塞队列的几个变种的,上面的代码中选择的是LinkedBlockingQueue型,这种队列的默认容量是没有
上界的,但是,也可以自己手动的设置最大容量。此外还有LinkedBlockingDeque型这是一个双端队列版本、ArrayBlockingQueue是可以用来设置是否需要公平性的队列、PriorityBlockingQueue是一种带优先级的队列,而不是简单的先进先出的队列,元素会按照他们的优先级顺序被移出,该类型也是没有容量上限的。