《java并发编程实战》基础构建模块(三)

双端队列与工作密取

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);
	}
}
上面的例子用闭锁实现测试多个线程并发的执行时间。比以前我们开两个线程并发执行严谨多了。

你可能感兴趣的:(《java并发编程实战》基础构建模块(三))