Semaphore实现信号量。 java
Semaphore能够维护当前访问自身的线程个数,并提供了同步机制。使用Semaphore能够控制同时访问资源的线程个数。例如:实现一个文件容许的并发访问数。 并发
单个信号量的Semaphore对象能够实现互斥锁的功能,而且能够是由一个线程得到了锁,再由另外一个线程释放锁。这可应用于死锁恢复的一些场合。 dom
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; public class SemaphoreTest { public static void main(String[] args) { ExecutorService es = Executors.newCachedThreadPool(); final Semaphore sp = new Semaphore(3); for (int i = 0; i < 10; i++) { Runnable r = new Runnable() { @Override public void run() { try { sp.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程"+Thread.currentThread().getName()+"进入,当前已有并发"+(3-sp.availablePermits())); try { Thread.sleep(new Random().nextInt(10000)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程"+Thread.currentThread().getName()+"即将离开"); sp.release(); System.out.println("线程"+Thread.currentThread().getName()+"已离开,当前已有并发"+(3-sp.availablePermits())); } }; es.execute(r); } es.shutdown(); } }
障碍器。表示你们彼此等待,你们集合好后才开始出发,分散活动后又在指定地点集合碰面。 ide
import java.util.Date; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CyclicBarrierTest { public static void main(String[] args) { ExecutorService es = Executors.newCachedThreadPool(); final CyclicBarrier cb = new CyclicBarrier(5); for (int i = 0; i < 5; i++) { Runnable r = new Runnable() { @Override public void run() { try { Thread.sleep(new Random().nextInt(10000)); System.out.println(new Date()+":线程"+Thread.currentThread().getName()+"到达目的地1,当前已到达"+(cb.getNumberWaiting()+1)+",正在等候"); cb.await(); System.out.println(new Date()+":全部线程已到达,向目的地2出发"); Thread.sleep(new Random().nextInt(10000)); System.out.println(new Date()+":线程"+Thread.currentThread().getName()+"到达目的地2,当前已到达"+(cb.getNumberWaiting()+1)+",正在等候"); cb.await(); System.out.println(new Date()+":全部线程已到达,向目的地3出发"); Thread.sleep(new Random().nextInt(10000)); System.out.println(new Date()+":线程"+Thread.currentThread().getName()+"到达目的地3,当前已到达"+(cb.getNumberWaiting()+1)+",正在等候"); cb.await(); System.out.println(new Date()+":全部线程已到达,任务结束"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }; es.execute(r); } es.shutdown(); } }
犹如倒计时计数器,调用CountDownLatch对象的countDown()方法就将计数器-1,当计数器到达0时,则全部等待者或者单个等待着开始执行。 ui
import java.util.Date; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CountDownLatchTest { public static void main(String[] args) { ExecutorService es = Executors.newCachedThreadPool(); final CountDownLatch cdOrder = new CountDownLatch(1); final CountDownLatch cdAnswer = new CountDownLatch(5); for (int i = 0; i < 5; i++) { Runnable r = new Runnable() { @Override public void run() { try { //Thread.sleep(new Random().nextInt(10000)); System.out.println(new Date()+":线程"+Thread.currentThread().getName()+"准备接受命令"); cdOrder.await(); System.out.println(new Date()+":线程"+Thread.currentThread().getName()+"已接受命令"); Thread.sleep(new Random().nextInt(10000)); System.out.println(new Date()+":线程"+Thread.currentThread().getName()+"处理命令"); cdAnswer.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }; es.execute(r); } try { Thread.sleep(new Random().nextInt(10000)); System.out.println(new Date()+":线程"+Thread.currentThread().getName()+"即将发布命令"); cdOrder.countDown(); System.out.println(new Date()+":线程"+Thread.currentThread().getName()+"已发布命令,正等待结果"); cdAnswer.await(); System.out.println(new Date()+":线程"+Thread.currentThread().getName()+"已收到全部响应结果"); } catch (Exception e) { e.printStackTrace(); } es.shutdown(); } }
Exchanger用于两个线程之间的数据交换。每一个线程在完成必定任务后想与对方交换数据,第一个先拿出数据的线程将一直等待第二个线程拿着数据的到来,才能彼此交换数据。 spa
import java.util.Date; import java.util.Random; import java.util.concurrent.Exchanger; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Exchanger交换机 两个线程之间用户交换数据 */ public class ExchangerTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); // 线程之间交换数据 final Exchanger exchanger = new Exchanger(); service.execute(new Runnable() { public void run() { try { String data = "【数据1】"; System.out.println(new Date()+":"+Thread.currentThread().getName() + "准备把" + data + "换出去"); Thread.sleep(new Random().nextInt(10000)); String data2 = (String) exchanger.exchange(data); System.out.println(new Date()+":"+Thread.currentThread().getName() + "换回的数据是" + data2); } catch (InterruptedException e) { e.printStackTrace(); } } }); service.execute(new Runnable() { public void run() { try { String data = "【数据2】"; System.out.println(new Date()+":"+Thread.currentThread().getName() + "准备把" + data + "换出去"); Thread.sleep(new Random().nextInt(10000)); String data2 = (String) exchanger.exchange(data); System.out.println(new Date()+":"+Thread.currentThread().getName() + "换回的数据是" + data2); } catch (Exception e) { e.printStackTrace(); } } }); } }