双端队列与工作密取
java 6增加了Deque和BlockingDeque,分别对Queue和BlockingQueue进行了扩展。
阻塞队列适用于生产者-消费者模式,双端队列适用于工作密取(Work Stealing)模式。在生产者-消费者设计中,所有的消费者共享一个工作队列,在工作密取设计中,每个消费者都有自己的双端队列。如果一个消费者自己的双端队列中的任务取完了,那么它可以到其它消费者的双端队列的另一端(尾部)秘密地获取工作来执行,降低了队列上的竞争程度,提高了队列的伸缩性。
工作密取非常适用于既是消费者也是生产者的问题-当执行一个工作时可能导致出现更多的工作。双端队列和工作密取确保了每个线程都保持忙碌状态。
阻塞方法与中断方法
中断是一种协作机制。当在代码中调用了一个将抛出InterruptedException异常的方法时,对于库代码来说,有两种处理的方法:
一.传递InterruptedException
二.恢复中断状态
同步工具类
信号量、栅栏、闭锁。
闭锁可以用来确保某些活动直到其他活动都完成后才继续执行。例如,在多玩家游戏中的所有玩家都就绪之后才能继续执行。启动门可以确保所有的线程一起并发开始,结束门使得主线程能够等待最后一个线程执行完成,而不是顺序地等待每一个线程执行完成。
import java.util.concurrent.CountDownLatch;
public class TestHarness {
public long timeTasks(int nThreads, final Runnable task)
throws InterruptedException {
final CountDownLatch startGate = new CountDownLatch(1);
final CountDownLatch endGate = new CountDownLatch(nThreads);
for (int i = 0; i < nThreads; i++) {
Thread t = new Thread() {
@Override
public void run() {
try {
//所有线程都必须在开始门等待
startGate.await();
try {
task.run();
} finally {
endGate.countDown();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t.start();
}
long start = System.nanoTime();
//在开始门处放行所有等待的线程
startGate.countDown();
//主线程等待所有并发子线程结束
endGate.await();
long end = System.nanoTime();
return end - start;
}
public static void main(String[] args) throws InterruptedException {
TestHarness obj = new TestHarness();
long time = obj.timeTasks(50, new Runnable() {
@Override
public void run() {
try {
//模拟耗时操作
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println(time);
}
}
上面的例子用闭锁实现测试多个线程并发的执行时间。比以前我们开两个线程并发执行严谨多了。