[本文是我对Java Concurrency In Practice 5.5的归纳和总结. 转载请注明作者和出处, 如有谬误, 欢迎在评论中指正. ]
Synchronizers
synchronizer是指那些根据状态协调线程的对象. BlockingQueue就是一个典型的synchronizer: 当队列为空时, 取数据的消费者线程将被阻塞, 直到队列不为空; 当队列满时, 存入数据的生产者线程将被阻塞, 直到队列不满. 除了BlockingQueue之外, 常用的synchronizer还有latch, FutureTask, semaphore, barrier等.
latch
latch相当于一个gate, 当latch到达特定的状态之前, gate是关闭的, 此时所有线程将被阻塞, 只有latch到达了特定状态, 线程才能通过gate.
CountDownLatch是latch的具体实现, CountDownLatch内部维护了一个计数器, 初始化CountDownLatch时需要指定计数器的初始值. 该初始值表示需要等待完成的事件的个数. 每调用一次countDown方法, 表示其中一个事件已经完成, 计数器的值将减一. 当计数器减为0时, gate才会打开:
public class TestHarness {
/**
* 计算nThreads个线程并发执行task所需的时间
*/
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() {
public void run() {
try {
// 直到startGate内部计数器减为0时才能从await中唤醒
startGate.await();
try {
task.run();
} finally {
// 完成了一件任务后将endGate减1
endGate.countDown();
}
} catch (InterruptedException ignored) {
}
}
};
t.start();
}
long start = System.nanoTime();
// 将startGate内部的计数器减1, 打开startGate
startGate.countDown();
// 直到endGate内部计数器减为0时才能从await中唤醒
endGate.await();
long end = System.nanoTime();
return end - start;
}
}
FutureTask
FutureTask用于执行任务, 其get方法将返回任务的执行结果. FutureTask常用的构造函数为FutureTask(Callable<V> callable), 使用Callable封装任务. FutureTask对象具有三种状态: 等待运行, 正在运行, 已完成. 当FutureTask对象处于已完成状态时调用get方法, get方法将立即返回计算结果, 否则get方法会阻塞, 直到FutureTask转变为已完成状态. 计算完成, 抛出异常, 或者被取消都会使得FutureTask的状态变为已完成.
FutureTask的常见使用场景是封装一个耗时任务, 然后提前开始计算, 当需要计算结果时, 再调用其get方法, 这样可以减少等待计算完成的时间.
使用FutureTask的例子:
public class Preloader {
private final FutureTask<ProductInfo> future = new FutureTask<ProductInfo>(new Callable<ProductInfo>() {
public ProductInfo call() throws DataLoadException {
// loadProductInfo方法用于加载产品信息, 这是一个耗时操作
return loadProductInfo();
}
});
// FutureTask实现了Runnable接口, 因此可以将future对象放进thread中执行
private final Thread thread = new Thread(future);
// 提供start方法启动线程, 而不是在构造方法中直接启动是为了防止this逃逸
public void start() {
// 启动thread, 执行future
thread.start();
}
// 当需要计算结果时, 就调用get方法获得产品信息的加载结果.
public ProductInfo get() throws DataLoadException, InterruptedException {
try {
// get方法将阻塞, 直到产品信息加载完成, 或者抛出异常
return future.get();
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof DataLoadException)
throw (DataLoadException) cause;
else
throw launderThrowable(cause);
}
}
public static RuntimeException launderThrowable(Throwable t) {
if (t instanceof RuntimeException)
return (RuntimeException) t;
else if (t instanceof Error)
throw (Error) t;
else
throw new IllegalStateException("Not unchecked", t);
}
}
semaphore--信号量
semaphore用于管理permit, 创建Semaphore对象时, 需要指定permit的最大个数. 调用acquire()方法申请从Semaphore对象中获取一个permit, 如果当前semaphore对象没有可用的permit, 线程将被阻塞, 直到有可用的permit. 调用release()方法将permit放回Semaphore对象. permit不与线程绑定, 一个线程申请的permit, 可以在另一个线程里release. semaphore通常用于实现资源池, 如数据库连接池等. semaphore也可以用于实现有界的集合, 如:
/**
* 有界的set集合
*/
public class BoundedHashSet<T> {
private final Set<T> set;
private final Semaphore sem;
public BoundedHashSet(int bound) {
this.set = Collections.synchronizedSet(new HashSet<T>());
// 设定Semaphore对象中的permit的最大个数
sem = new Semaphore(bound);
}
public boolean add(T o) throws InterruptedException {
// 每次add时就向semaphore对象申请一个permit
sem.acquire();
boolean wasAdded = false;
try {
wasAdded = set.add(o);
return wasAdded;
}
finally {
if (!wasAdded)
// 当申请失败是release permit
sem.release();
}
}
public boolean remove(Object o) {
boolean wasRemoved = set.remove(o);
if (wasRemoved)
// 成功移除后将permit release
sem.release();
return wasRemoved;
}
}
CyclicBarrier
CyclicBarrier允许一组线程互相等待, 直到该组线程全部到达某个公共屏障点. 创建CyclicBarrier时需要指定线程组中线程的数量. 调用CyclicBarrier对象的await方法, 表示当前线程已到达公共屏障点, 然后等待其他线程到达. 当所有线程到达公共屏障点后, CyclicBarrier对象将释放线程组, 然后重置CyclicBarrier对象的状态. 因此CyclicBarrier对象是可以循环使用的. 如果有线程在等待期间超时或者被中断, 该CyclicBarrier对象被视为已损坏, 随后对await方法的调用都要抛出BrokenBarrierException异常.
分享到:
相关推荐
《HibernateSynchronizer-3.1.9:JavaWeb数据库开发的强大工具》 在JavaWeb开发领域,数据库的管理和同步是至关重要的环节。HibernateSynchronizer-3.1.9作为一个强大的工具,专为Java开发者提供了高效且便捷的...
资源分类:Python库 所属语言:Python 资源全名:synchronizer-2.0.0a0.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
《Hibernate Synchronizer 3.1.1:Eclipse 插件助力Hibernate映射文件自动化》 在Java开发领域,Hibernate作为一个强大的对象关系映射(ORM)框架,极大地简化了数据库操作。然而,手动管理Hibernate的映射文件(....
HibernateSynchronizer hibernate配置文件生成工具
"slide-synchronizer-as-a-service" 是一个基于Ruby构建的服务,专门用于实现幻灯片的同步功能。在讲解这个项目之前,我们先了解一下Ruby这门编程语言。Ruby是一种面向对象的、动态类型的脚本语言,它以其简洁的语法...
《深入理解Hibernate Synchronizer 3.1.9:整合与优化》 Hibernate Synchronizer是一款强大的工具,专为简化Hibernate在Eclipse环境中的配置和管理而设计。它通过自动同步数据库模型与Java实体类,极大地提升了开发...
**WMS Synchronizer-crx插件详解** WMS Synchronizer是一款专为管理库存而设计的Chrome浏览器扩展程序,其主要功能是实现与仓库管理系统(Warehouse Management System,简称WMS)之间的数据同步。这款插件的核心...
【标题】"LRC Synchronizer - 开源" 在音乐播放体验中,歌词同步往往能够提升听众对歌曲的理解和享受。LRC Synchronizer 是一个专门针对这一需求开发的开源程序,它允许用户将歌词(通常以 .lrc 格式存储)与使用 ...
**syncpath - C++ 轻量级同步器** `syncpath` 是一款基于 C++ 开发的开源软件,设计为轻量级的命令行工具,适用于多种操作系统平台。其主要功能是同步两个目录的内容,使得源目录和目标目录保持一致。...
《Directories Synchronizer:开源目录同步利器》 在数字化时代,数据管理变得至关重要,而文件同步作为其中的一个重要环节,能够确保多设备间的数据一致性,防止数据丢失。"Directories Synchronizer"是一款开源的...
Subtitle Synchronizer是一款开源的命令行工具,专为调整subrip(srt)字幕文件的时间对齐而设计。在处理视频与字幕不同步的问题时,它提供了一个高效的解决方案,使得用户能够精确地调整字幕与视频内容的匹配度。这...
"File and Directory Synchronizer" 是一个专为此目的而设计的开源应用程序,名为 "fileSync"。这个工具采用C#编程语言编写,并基于较早版本的.NET Framework 1.1构建,它展示了C#和.NET平台在处理文件系统操作方面...
作为一款开源软件,"delicious synchronizer"为用户提供了高效便捷的解决方案,它允许用户在流行的在线书签服务del.icio.us(美味书签)与本地的Internet Explorer收藏夹之间实现无缝同步。这一创新技术极大地提升了...
《Address Book Synchronizer——开源的力量,保护你的联系人信息》 在当今信息化社会,电子邮件地址簿是我们日常沟通的重要组成部分,它储存了我们与亲朋好友、同事客户间的联系方式。然而,一旦这些宝贵的数据...
Ruby File Synchronizer 是一个基于 Ruby 语言开发的开源文件同步工具,它的设计目标是提供一个功能强大且用户友好的界面,与市面上流行的文件同步软件相媲美。这个项目利用了 Fox 工具箱,这是一个用于创建图形用户...
《开源的Pocket Universal Synchronizer:打造无缝联系人同步体验》 在当今信息化社会,个人设备中的联系人数据是我们日常沟通的重要桥梁。随着PocketPC和MS Mobile设备的普及,用户对于设备间的同步需求日益增强,...
XBMC AntMovieCatalog Synchronizer 是一款开源工具,专门设计用于帮助用户同步他们的Ant Movie Catalog与XBMC(Xbox Media Center)之间的电影数据。这款工具的出现,旨在为电影收藏爱好者提供一个便捷的方式,使...
"Yet Another File Synchronizer" 是一个开源的文件同步工具,其主要功能是实现源文件与目标文件之间的层次结构同步。这个工具的核心是基于Java开发的库,这意味着它具有跨平台性,可以在多种操作系统上运行,如...
"Innox AdoDB Synchronizer" 是一个开源的数据库同步工具,主要功能是对比和同步两个不同的数据库系统中的数据模式和记录。这个程序的核心亮点在于它利用了 AdoDB 这个强大的数据库抽象层库,使得它具备了跨多种...