一、java.util.concurrent.Semaphore
/** * Semaphore * 一个计数信号量。 * 从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。 * 每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。 * Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。 * 获得一项前,每个线程必须从信号量获取许可,从而保证可以使用该项。 * 该线程结束后,将项返回到池中并将许可返回到该信号量,从而允许其他线程获取该项。 * 注意,调用 acquire() 时无法保持同步锁,因为这会阻止将项返回到池中。信号量封装所需的同步,以限制对池的访问,这同维持该池本身一致性所需的同步是分开的。 * 将信号量初始化为 1,使得它在使用时最多只有一个可用的许可,从而可用作一个相互排斥的锁。 * 这通常也称为二进制信号量,因为它只能有两种状态:一个可用的许可,或零个可用的许可。 * 按此方式使用时,二进制信号量具有某种属性(与很多 Lock 实现不同),即可以由线程释放“锁”,而不是由所有者(因为信号量没有所有权的概念)。在某些专门的上下文(如死锁恢复)中这会很有用 * 此类的构造方法可选地接受一个公平 参数。当设置为 false 时,此类不对线程获取许可的顺序做任何保证 * 当公平设置为 true 时,信号量保证对于任何调用获取方法的线程而言,都按照处理它们调用这些方法的顺序(即先进先出;FIFO)来选择线程、获得许可。 * 非同步的 tryAcquire 方法不使用公平设置,而是使用任意可用的许可。 * 通常,应该将用于控制资源访问的信号量初始化为公平的,以确保所有线程都可访问资源。 * 为其他的种类的同步控制使用信号量时,非公平排序的吞吐量优势通常要比公平考虑更为重要。 * 此类还提供便捷的方法来同时 acquire 和释放多个许可。小心,在未将公平设置为 true 时使用这些方法会增加不确定延期的风险 */ public class Semaphore implements Serializable { //构造方法 //创建具有给定的许可数和非公平的公平设置的 Semaphore public Semaphore(int permits){} //创建具有给定的许可数和给定的公平设置的 Semaphore public Semaphore(int permits, boolean fair){} //常用方法 //从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。 public void acquire() throws InterruptedException{} //释放一个许可,将其返回给信号量 public void release(){} //返回此信号量中当前可用的许可数。 此方法通常用于调试和测试目的。 public int availablePermits(){} //返回标识此信号量的字符串,以及信号量的状态。括号中的状态包括 String 类型的 "Permits =",后跟许可数。 public String toString(){} //返回正在等待获取的线程的估计数目 public final int getQueueLength(){} //返回一个 collection,包含可能等待获取的线程。 protected Collection<Thread> getQueuedThreads() }
二、示例
import java.util.concurrent.*; public class SemaphoreTest { public static void main(String[] args) { ExecutorService threadPool = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(3); for(int i=0;i<10;i++) { Runnable run = new Runnable(){ public void run(){ try{ semaphore.acquire(); }catch ( InterruptedException e ){} System.out.println("线程"+Thread.currentThread().getName()+"进入,当前已经有 "+(3-semaphore.availablePermits())+" 个线程进入"); try{ Thread.sleep(1000); }catch ( InterruptedException e ){} System.out.println("线程"+Thread.currentThread().getName()+"即将离开"); semaphore.release(); System.out.println("线程"+Thread.currentThread().getName()+"已经离开,当前剩余 "+semaphore.availablePermits()+" 个信号量"); } }; threadPool.execute(run); } threadPool.shutdown(); } }
- 由上例可以看出,其实Semaphore也相当于一个锁,只不过可以指定并发的线程数,而不是一次只能进一个线程
三、java.util.concurrent.CyclicBarrier
/** * CyclicBarrier * 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。 * 在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。 * 因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。 * CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。 * 若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。 */ public class CyclicBarrier { //创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在启动 barrier 时执行预定义的操作 public CyclicBarrier(int parties){} //创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行。 public CyclicBarrier(int parties, Runnable barrierAction){} //在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。 public int await() throws InterruptedException, BrokenBarrierException{} //返回当前在屏障处等待的参与者数目。 public int getNumberWaiting(){} //返回要求启动此 barrier 的参与者数目。 public int getParties(){} }
四、示例
import java.util.concurrent.*; import java.util.*; class CyclicBarrierTest { public static void main(String[] args) { ExecutorService threadPool = Executors.newCachedThreadPool(); final CyclicBarrier barrier = new CyclicBarrier(3,new Runnable(){ public void run(){ System.out.println(Thread.currentThread().getName()+" 所有人都到齐了,继续。。。"); } }); for(int i=0;i<3;i++) { Runnable run = new Runnable(){ public void run(){ try{ Thread.sleep(1000*(new Random().nextInt(10))); System.out.println("线程 "+Thread.currentThread().getName()+" 已到达集合点1,当前已有 "+(barrier.getNumberWaiting()+1)+" 个人在等待"); barrier.await(); Thread.sleep(1000*(new Random().nextInt(10))); System.out.println("线程 "+Thread.currentThread().getName()+" 已到达集合点2,当前已有 "+(barrier.getNumberWaiting()+1)+" 个人在等待"); barrier.await(); Thread.sleep(1000*(new Random().nextInt(10))); System.out.println("线程 "+Thread.currentThread().getName()+" 已到达集合点3,当前已有 "+(barrier.getNumberWaiting()+1)+" 个人在等待"); barrier.await(); Thread.sleep(1000*(new Random().nextInt(10))); System.out.println("线程 "+Thread.currentThread().getName()+" 已到达集合点4,当前已有 "+(barrier.getNumberWaiting()+1)+" 个人在等待"); barrier.await(); }catch(Exception e){} } }; threadPool.execute(run); } threadPool.shutdown(); } }
五、java.util.concurrent.CountDownLatch
/** * CountDownLatch * 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 * 用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。 * 之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。 * 这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。 * CountDownLatch 是一个通用同步工具,它有很多用途。 * 将计数 1 初始化的 CountDownLatch 用作一个简单的开/关锁存器,或入口: * 在通过调用 countDown() 的线程打开入口前,所有调用 await 的线程都一直在入口处等待。 * 用 N 初始化的 CountDownLatch 可以使一个线程在 N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N 次之前一直等待。 */ public class CountDownLatch { //构造一个用给定计数初始化的 CountDownLatch public CountDownLatch(int count){} //使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。 public void await() throws InterruptedException{} //递减锁存器的计数,如果计数到达零,则释放所有等待的线程 public void countDown(){} //返回当前计数。此方法通常用于调试和测试 public long getCount(){} }
六、示例
import java.util.concurrent.*; import java.util.*; class CountDownLatchTest { public static void main(String[] args) { ExecutorService threadPool = Executors.newCachedThreadPool(); final CountDownLatch cdHandler = new CountDownLatch(1); final CountDownLatch cdSportsman = new CountDownLatch(3); final List<String> result = new ArrayList<String>(); for(int i=0;i<3;i++) { Runnable run = new Runnable(){ public void run(){ try{ System.out.println("运动员:"+Thread.currentThread().getName()+"正在准备冲刺。。。"); cdHandler.await(); System.out.println("运动员:"+Thread.currentThread().getName()+"开始冲刺--->>>>"); Thread.sleep((long)(Math.random()*10000)); System.out.println("运动员:"+Thread.currentThread().getName()+"已达到终点!"); result.add(Thread.currentThread().getName()); cdSportsman.countDown(); }catch (Exception e ){} } }; threadPool.execute(run); } try{ Thread.sleep((long)(Math.random()*10000)); System.out.println("裁判员:"+Thread.currentThread().getName()+"扣动扳机! 啪!!!!!!!!"); cdHandler.countDown(); cdSportsman.await(); System.out.println("比赛结束,裁判员:"+Thread.currentThread().getName()+"公布比赛结果:"); for(int i=1;i<4;i++) System.out.println("第"+i+"名: "+result.get(i-1)); }catch(Exception e){} threadPool.shutdown(); } }
七、java.util.concurrent.Exchanger<V>
/** * Exchanger<V> * 可以在对中对元素进行配对和交换的线程的同步点。 * 每个线程将条目上的某个方法呈现给 exchange 方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象。 * Exchanger 可能被视为 SynchronousQueue 的双向形式。Exchanger 可能在应用程序(比如遗传算法和管道设计)中很有用。 */ public class Exchanger<V> { //创建一个新的 Exchanger。 public Exchanger(){} //等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象。 public V exchange(V x) throws InterruptedException{} }
八、示例
import java.util.concurrent.*; class ExchangerTest { private static final Exchanger<String> changer = new Exchanger<String>(); static class Solder implements Runnable { public void run(){ try{ Thread.sleep((long)(Math.random()*10000)); System.out.println("卖东西的: "+Thread.currentThread().getName()+"达到指定地点"); String data = "物品"; String get = changer.exchange(data); System.out.println("卖东西的: "+Thread.currentThread().getName()+"收到"+get+",马上撤退...."); }catch(Exception e){} } } static class Buyer implements Runnable { public void run(){ try{ Thread.sleep((long)(Math.random()*10000)); System.out.println("----买东西的: "+Thread.currentThread().getName()+"达到指定地点"); String data = "money"; String get = changer.exchange(data); System.out.println("----买东西的: "+Thread.currentThread().getName()+"收到"+get+",马上撤退...."); }catch(Exception e){} } } public static void main(String[] args) { new Thread(new Solder()).start(); new Thread(new Buyer()).start(); } }
相关推荐
1. java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...
java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...
Java.util.concurrent是Java 5.0引入的一个重要包,它为多线程编程提供了一组高级并发工具。这个包的设计者是Doug Lea,它的出现是JSR-166的一部分,也被称作Tiger更新。Java.util.concurrent的引入是为了解决传统...
`java.util.concurrent`包中的`AbstractQueuedSynchronizer`框架为Java开发者提供了一个强大的工具箱,使得他们能够高效地实现各种同步器。通过对同步状态的有效管理、阻塞和唤醒机制的优化以及灵活的扩展性设计,...
描述中提到了“Java并发编程工具包java.util.concurrent的UML类结构图 PDF”,这强调了文件是一个图表,它可能包括并发包中的线程安全集合、同步器、线程池、执行器等核心组件的类图和接口图。 标签“Java ...
1. java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...
文档标题“java.util.concurrent同步器框架”和描述“Doug Lea的java.util.concurrent同步器框架”表明本文将探讨由Doug Lea所撰写的关于Java并发编程中同步器框架的内容。文档中提到了AbstractQueuedSynchronizer类...
Java并发工具包(java.util.concurrent)是Java平台上用于高效、安全地处理多线程编程的重要组件。这个包包含了丰富的并发工具类,旨在帮助开发者构建高度并发的程序,提高程序的性能和可伸缩性。本资源是该工具包的...
除了上述两种同步工具之外,`java.util.concurrent` 包还提供了其他有用的类,如 `CyclicBarrier` 和 `Exchanger` 等,它们都是为了简化并发编程而设计的。 - **CyclicBarrier**:允许一组线程互相等待,直到所有...
在Java并发编程中,`java.util.concurrent`(简称JUC)提供了丰富的类和接口,如Executor框架、线程池、并发集合、同步工具类等。这些工具使得程序员能够更方便地管理线程,避免了传统的锁和同步机制带来的复杂性和...
`java.util.concurrent` 包(简称JUC)是Java提供的一个强大的并发工具包,它提供了丰富的并发组件,如线程池、并发容器、锁和同步机制等,极大地简化了并发编程的复杂性。本篇文章将深入探讨如何使用`java.util....
本文将详细探讨Atlassian发布的`atlassian-util-concurrent-0.0.12.jar`库,这是一个专门针对并发处理的工具集,旨在简化Java开发中的多线程操作。 `atlassian-util-concurrent-0.0.12.jar.zip`是这个库的压缩文件...
Synchronized和java.util.concurrent.locks.Lock都是Java中用于实现线程同步的关键字和接口,它们的主要目标是保证多线程环境下的数据一致性与并发安全。然而,两者在使用方式、控制粒度以及灵活性方面存在显著差异...
在Java编程语言中,`java.util.Vector`是一个重要的集合类,它是`ArrayList`的早期版本,提供了线程安全的动态数组实现。这篇文章将对`Vector`类进行详细的总结,包括其特点、用法以及与`ArrayList`的区别。 1. **...
Java.util.concurrent(JUC)是Java平台中的一个核心包,专门用于处理多线程并发问题。这个包包含了大量的工具类和接口,极大地简化了并发编程的复杂性,提高了程序的性能和可伸缩性。本测试源文件主要是针对JUC并发...
`java.util.concurrent`包是Java提供的一个强大的多线程工具库,其中包含了许多类和接口,如`CountDownLatch`和`CyclicBarrier`,它们为程序员提供了更高级别的同步和协调机制。这篇文档将详细解析这两个工具类的...
Java并发工具包java.util.concurrent是Java平台在Java 5版本中引入的一组新的并发编程类库,旨在帮助Java开发者更容易地实现复杂的并发程序。这一包的出现,极大地简化了开发者在处理线程和数据同步时所遇到的难题,...