for (String s : messages) drop.put(s); drop.put(\
}catch (InterruptedException intEx) {
System.out.println(\ \ } } }
class Consumer implements Runnable{ private BlockingQueue
public Consumer(BlockingQueue
public void run(){ try{
String msg = null;
while (!((msg = drop.take()).equals(\ System.out.println(msg); }catch (InterruptedException intEx) { System.out.println(\ \ } } }
public class SynQApp{
public static void main(String[] args) {
BlockingQueue
实现代码看起来几乎相同,但是应用程序有额外获益:SynchronousQueue 允许在队列进行一个插入,只要有一个线程等着使用它。
在实践中,SynchronousQueue 类似于 Ada 和 CSP 等语言中可用的 “会合通道”。这些通道有时在其他环境中也称为 “连接”,这样的环境包括 .NET (见 参考资料)。
结束语
当 Java 运行时知识库提供便利、预置的并发性时,为什么还要苦苦挣扎,试图将并发性导入到您的 Collections 类?本系列的下一篇文章将会进一步探讨 java.util.concurrent 名称空间的内容。
参考资料
学习 ? ? ? ? ?
“Java 理论与实践: 并发集合类”(Brian Goetz,developerWorks,2003 年 7 月):学习 Doug Lea “使用泛型和并发改善集合”(John Zukowski,developerWorks,2008 年 4 月):介绍 Java 6 中 Package java.util.concurrent, Java platform SE 6:进一步学习本文讨论的工具类。 Guarded Blocks:协调线程最常用的惯用语。
“Introduction to the Collections Framework”(MageLang Institute,Sun Developer Network,1999 的 util.concurrent 包如何为标准集合类型 List 和 Map 注入新的活力。 Java Collections Framework 的变化。
年):这篇教程是很早以前的,但是很棒,它对并发集合之前的 Java Collections Framework 做了完整介绍。 ? ? ? 讨论 ?
加入 My developerWorks 社区。
“The Collections Framework”:阅读 Sun Microsystems 的 Java Collections Framework 和 API 文档。 The Joins Concurrency Library: Microsoft? Research 发布这个库,将连接 实现为一个同步机制;developerWorks Java 技术专区: 关于 Java 编程各个方面的数百篇文章。
相关的研究报告(PDF 格式)是学习连接背后理论的良好资源。
关于 java.util.concurrent 您不知道的 5 件事2
并发编程意味着更智慧地工作,而不是更困难地工作
简介: 除了具有很好的并发性的 Collections,java.util.concurrent 还引入了其他一些预先构建的组件,它们可帮助您调整和执行多线程应用程序中的线程。Ted Neward 介绍在 Java? 编程过程中使用 java.util.concurrent 包要注意的 5 点。
发布日期: 2010 年 7 月 09 日 级别: 初级 其他语言版本: 英文
并发 Collections 提供了线程安全、经过良好调优的数据结构,简化了并发编程。然而,在一些情形下,开发人员需要更进一步,思考如何调节和/或限制线程执行。由于 java.util.concurrent 的总体目标是简化多线程编程,您可能希望该包包含同步实用程序,而它确实包含。
本文是 第 1 部分 的延续,将介绍几个比核心语言原语(监视器)更高级的同步结构,但它们还未包含在 Collection 类中。一旦您了解了这些锁和门的用途,使用它们将非常直观。
关于本系列
您觉得自己懂 Java 编程?事实是,大多数开发人员都只领会到了 Java 平台的皮毛,所学也只够应付工作。在本 系列 中,Ted Neward 深度挖掘 Java 平台的核心功能,揭示一些鲜为人知的事实,帮助您解决最棘手的编程困难。
1. Semaphore
在一些企业系统中,开发人员经常需要限制未处理的特定资源请求(线程/操作)数量,事实上,限制有时候能够提高系统的吞吐量,因为它们减少了对特定资源的争用。尽管完全可以手动编写限制代码,但使用 Semaphore 类可以更轻松地完成此任务,它将帮您执行限制,如清单 1 所示:
清单 1. 使用 Semaphore 执行限制 import java.util.*;import java.util.concurrent.*;
public class SemApp{
public static void main(String[] args) { Runnable limitedCall = new Runnable() { final Random rand = new Random();
final Semaphore available = new Semaphore(3); int count = 0; public void run() {
int time = rand.nextInt(15); int num = count++; try{
available.acquire();
System.out.println(\ Thread.sleep(time * 1000);
System.out.println(\ available.release();
} catch (InterruptedException intEx) { intEx.printStackTrace(); } } };
for (int i=0; i<10; i++)
new Thread(limitedCall).start(); } }
即使本例中的 10 个线程都在运行(您可以对运行 SemApp 的 Java 进程执行 jstack 来验证),但只有 3 个线程是活跃的。在一个信号计数器释放之前,其他 7 个线程都处于空闲状态。(实际上,Semaphore 类支持一次获取和释放多个 permit,但这不适用于本场景。)
2. CountDownLatch
如果 Semaphore 是允许一次进入一个(这可能会勾起一些流行夜总会的保安的记忆)
线程的并发性类,那么 CountDownLatch 就像是赛马场的起跑门栅。此类持有所有空闲线程,直到满足特定条件,这时它将会一次释放所有这些线程。
清单 2. CountDownLatch:让我们去赛马吧! import java.util.*;
import java.util.concurrent.*;
class Race{
private Random rand = new Random();
private int distance = rand.nextInt(250); private CountDownLatch start; private CountDownLatch finish;
private List
public Race(String... names) {
this.horses.addAll(Arrays.asList(names)); }
public void run() throws InterruptedException{
System.out.println(\ final CountDownLatch start = new CountDownLatch(1);
final CountDownLatch finish = new CountDownLatch(horses.size());
final List
for (final String h : horses) { new Thread(new Runnable() { public void run() { try{
System.out.println(h + \ start.await();
int traveled = 0;
while (traveled < distance) {
// In a 0-2 second period of time.... Thread.sleep(rand.nextInt(3) * 1000);
// ... a horse travels 0-14 lengths traveled += rand.nextInt(15);
System.out.println(h + \ }
finish.countDown();
System.out.println(h + \ places.add(h);
}catch (InterruptedException intEx) {
System.out.println(\ intEx.printStackTrace(); } } }).start(); }
System.out.println(\ start.countDown();
finish.await();
System.out.println(\ System.out.println(places.get(0) + \ System.out.println(places.get(1) + \
System.out.println(\ } }
public class CDLApp{
public static void main(String[] args) throws InterruptedException, java.io.IOException{ System.out.println(\
Race r = new Race( \ \ \ \ \
\ \ );
System.out.println(\ System.out.println(\ System.in.read(); r.run(); } }
注意,在 清单 2 中,CountDownLatch 有两个用途:首先,它同时释放所有线程,模拟马赛的起点,但随后会设置一个门闩模拟马赛的终点。这样,“主” 线程就可以输出结果。 为了让马赛有更多的输出注释,可以在赛场的 “转弯处” 和 “半程” 点,比如赛马跨过跑道的四分之一、二分之一和四分之三线时,添加 CountDownLatch。