j.u.c同步器使用总结
从jdk1.5开始,java.util.concurrent提供了在并发编程中很常用的实用工具类,包括几个小的、已标准化的可扩展框架,以及一些提供有用功能的类。没有这些类,并发功能会很难实现或实现起来冗长乏味。本文将关注j.u.c中提供的四种同步器: CountDownLatch, CyclicBarrier, Semaphore, Exchanger,它们用于辅助实现一些常见的同步场景。下面将分别介绍java并发包中的每种同步器使用方法和常见场景。
一、CountDownLatch
1. 功能
用于同步多个线程的完成操作,让先完成的线程进行等待,直至所有线程完成。
2. 使用方法
1)新建CountDownLatch对象,定义总计数器latch。
2)调用await()方法,使当前线程进入等待状态。
3)调用countDown()方法,使计数器减一,当计数器降为0时,线程重新恢复运行。
3. 示例
场景: 10个同事约好周末一起去西湖游玩,先在公司集合完毕,到齐后一起出发,每人骑一辆自行车,统一在西湖集合。
import java.util.Random;import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class CountDownLatchTest {public static void main(String[] args) {final CountDownLatch start = new CountDownLatch(1);final CountDownLatch done = new CountDownLatch(10);ExecutorService executor = Executors.newFixedThreadPool(10);for(int i = 0; i<10; i++){executor.execute(new Employee(start, done));}start.countDown();System.out.println("大部队已经准备出发.");try {done.await();} catch (InterruptedException e) {}System.out.println("大部队在西湖集结完毕.");executor.shutdown();}}class Employee implements Runnable {private CountDownLatch start;private CountDownLatch done;public Employee(CountDownLatch start, CountDownLatch done){this.start = start;this.done = done;}@Overridepublic void run() {//到公司后等待try {start.await();} catch (InterruptedException e) {}System.out.println(Thread.currentThread() + "从公司出发,去西湖路上.");try {Thread.sleep(new Random().nextInt(5000));} catch (InterruptedException e1) {}//哥已经先到了done.countDown();}}import java.util.Random;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class CyclicBarrierTest {public static void main(String[] args) {final CyclicBarrier barrier = new CyclicBarrier(10, new Runnable(){@Overridepublic void run() {System.out.println("大部队集合完毕了。");}});ExecutorService executor = Executors.newFixedThreadPool(10);for(int i = 0; i<10; i++){final int num = i;executor.execute(new Runnable(){@Overridepublic void run() {System.out.println("num: " + num + " 从公司出发了.");try {Thread.sleep(new Random().nextInt(5000));barrier.await(); // 在西湖等待大部队System.out.println("num: " + num + " 在西湖开始游玩.");Thread.sleep(new Random().nextInt(5000));barrier.await(); //等待大部队就餐} catch (Exception e1) {}}});}executor.shutdown();}}import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;public class SemaphoreTest {public static void main(String[] args) {final Semaphore semaphore = new Semaphore(2,true);ExecutorService executor = Executors.newFixedThreadPool(10);for(int i = 0; i<10; i++){final int num = i;executor.execute(new Runnable(){@Overridepublic void run() {System.out.println("num: " + num + " 想要打游戏. 还有" + semaphore.availablePermits() + "台游戏机.");try {semaphore.acquire(1);} catch (InterruptedException e) {}System.out.println("num: " + num + " 开始打游戏. 还有" + semaphore.availablePermits() + "台游戏机.");try {Thread.sleep(5000);} catch (InterruptedException e1) {}semaphore.release();System.out.println("num: " + num + " 结束打游戏. 还有" + semaphore.availablePermits() + "台游戏机.");}});}executor.shutdown();}}import java.util.concurrent.Exchanger;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ExchangerTest {public static void main(String[] args) {final Exchanger exchanger = new Exchanger();ExecutorService executor = Executors.newCachedThreadPool();executor.execute(new Runnable(){@Overridepublic void run() {String money = "钞票";System.out.println("同事有: " + money);try {String goods1 = (String) exchanger.exchange(money);System.out.println("同事有: " + goods1);} catch (InterruptedException e) {}}});executor.execute(new Runnable(){@Overridepublic void run() {String goods2 = "小米手机";System.out.println("黄牛有: " + goods2);//黄牛很忙,迟到一会try {Thread.sleep(5000);} catch (InterruptedException e1) {}try {String money = (String) exchanger.exchange(goods2);System.out.println("黄牛有: " + money);} catch (InterruptedException e) {}}});executor.shutdown();}}