7 Java多线程:JUC(上)

您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~
前面把线程相关的生命周期、关键字、线程池(ThreadPool)、ThreadLocal、CAS、锁和AQS都讲完了,现在就剩下怎么来用多线程了 。而要想用好多线程 , 其实是可以取一些巧的,比如JUC(好多面试官喜欢问的JUC,就是现在要讲的JUC) 。JUC就是java.util.concurrent的首字母缩写,它是Java并发工具包就是中提供的各种工具类的统称,主要分为几大类:
1、同步器;
2、线程安全的容器;
3、阻塞队列;
4、一些特殊的类 。
他们都有各自适合应用场景 。这里是并发工具包相关类的继承结构:

7 Java多线程:JUC(上)

文章插图
下面从同步器开始 。
常用的JUC同步器有四个:
1、CountDownLatch:字面意思是倒计时锁 , 如果有“倒计时”的需求,那么CountDownLatch是最好的工具 。它还有一个别称:发令枪 。可以想象一下,火箭点火发射的时候,所有设备、部门都会依次检查确认,如果全部都确认准备好了才能开始发射,也就是等倒数到指定的数字(一般是0)的时候,就开始执行预设动作;
2、Semaphore:字面意思信号量 , 好比红绿灯,或者就餐排队时餐馆发的数字序号,一次只允许若干个线程执行 。这个在昨天的例子里面也已经演示过了,而且还是通过自定义AQS来实现的(信号量可能不太好理解,我更倾向于叫它摇号器);
3、CyclicBarrier:字面意思是屏障或者栅栏 , 与CountDownLatch比较像,但它侧重于工作本身,即指定的若干个工作都满足考核标准(某个屏障)之后,才能继续进行下面的工作 , 且可反复使用;
4、Exchanger:用于线程之间交换数据,更形象地说法是“交换机”,即当一个线程完成某项工作后想与另一个线程交换数据,就可以使用这个工具类 。
下面来一个个地演示它们的用法 。
一、CountDownLatch
CountDownLatch的功能如果用图来表示的话 , 就会是这样的:
7 Java多线程:JUC(上)

文章插图
CountDownLatch实例代码:
/** * 发令枪 * * @author 湘王 */public class CountDownLatchTester implements Runnable {static final CountDownLatch latch = new CountDownLatch(10);@Overridepublic void run() {// 检查任务try {System.out.println(Thread.currentThread().getName() + " 检查完毕!");} catch (Exception e) {e.printStackTrace();} finally {latch.countDown();}}public static void main(String[] args) throws InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(5);for (int i = 10; i > 0; i--) {Thread.sleep(1000);executor.submit(new CountDownLatchTester());System.out.println(i);}Thread.sleep(1000);// 检查latch.await();System.out.println();System.out.println("点火,发射!");// 关闭线程池executor.shutdown();}}执行CountDownLatch的效果是:
7 Java多线程:JUC(上)

文章插图
二、Semaphore
Semaphore的功能如果用图来表示的话,就会是这样的:
7 Java多线程:JUC(上)

文章插图
Semaphore实例代码:
/** * 信号量(摇号器) * * @author 湘王 */public class SemaphoreTester implements Runnable {static final Semaphore semaphore = new Semaphore(3);@Overridepublic void run() {try {semaphore.acquire();System.out.println(Thread.currentThread().getName() + " 开始进餐");Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}semaphore.release();}public static void main(String[] args) {ExecutorService excutor = Executors.newFixedThreadPool(15);for (int i = 0; i < 15; i++) {excutor.submit(new SemaphoreTester());}excutor.shutdown();}}Semaphore执行后的效果是:
7 Java多线程:JUC(上)

文章插图
三、CyclicBarrier
CyclicBarrier的功能如果用图来表示的话,就会是这样的:
7 Java多线程:JUC(上)

文章插图
CyclicBarrier实例代码:
/** * 栅栏 * * @author 湘王 */public class CyclicBarrierTester implements Runnable {private final static CyclicBarrier barrier = new CyclicBarrier(3);@Overridepublic void run() {try {Thread.sleep(1000);System.out.println(Thread.currentThread().getName() + " 已达到预定位置,等待指令...");// 只有最后一个线程执行后,所有的线程才能执行2barrier.await();Thread.sleep(1000);// 2 所有线程都会执行的动作System.out.println(Thread.currentThread().getName() + " 已突破第一道封锁线");} catch (Exception e) {e.printStackTrace();}}public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(3);for (int i = 0; i < 15; i++) {executor.submit(new CyclicBarrierTester());}// 关闭线程池executor.shutdown();}}

推荐阅读