您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~

前面把线程相关的生命周期、关键字、线程池(ThreadPool)、ThreadLocal、CAS、锁和AQS都讲完了,现在就剩下怎么来用多线程了。而要想用好多线程,其实是可以取一些巧的,比如JUC(好多面试官喜欢问的JUC,就是现在要讲的JUC)。JUC就是java.util.concurrent的首字母缩写,它是Java并发工具包就是中提供的各种工具类的统称,主要分为几大类:

1、同步器;

2、线程安全的容器;

3、阻塞队列;

4、一些特殊的类。

他们都有各自适合应用场景。这里是并发工具包相关类的继承结构:

下面从同步器开始。

常用的JUC同步器有四个:

1、CountDownLatch:字面意思是倒计时锁,如果有“倒计时”的需求,那么CountDownLatch是最好的工具。它还有一个别称:发令枪。可以想象一下,火箭点火发射的时候,所有设备、部门都会依次检查确认,如果全部都确认准备好了才能开始发射,也就是等倒数到指定的数字(一般是0)的时候,就开始执行预设动作;

2、Semaphore:字面意思信号量,好比红绿灯,或者就餐排队时餐馆发的数字序号,一次只允许若干个线程执行。这个在昨天的例子里面也已经演示过了,而且还是通过自定义AQS来实现的(信号量可能不太好理解,我更倾向于叫它摇号器);

3、CyclicBarrier:字面意思是屏障或者栅栏,与CountDownLatch比较像,但它侧重于工作本身,即指定的若干个工作都满足考核标准(某个屏障)之后,才能继续进行下面的工作,且可反复使用;

4、Exchanger:用于线程之间交换数据,更形象地说法是“交换机”,即当一个线程完成某项工作后想与另一个线程交换数据,就可以使用这个工具类。

下面来一个个地演示它们的用法。

一、CountDownLatch

CountDownLatch的功能如果用图来表示的话,就会是这样的:

CountDownLatch实例代码:

/**
* 发令枪
*
* @author 湘王
*/
public class CountDownLatchTester implements Runnable {
static final CountDownLatch latch = new CountDownLatch(10);
@Override
public 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的效果是:

二、Semaphore

Semaphore的功能如果用图来表示的话,就会是这样的:

Semaphore实例代码:

/**
* 信号量(摇号器)
*
* @author 湘王
*/
public class SemaphoreTester implements Runnable {
static final Semaphore semaphore = new Semaphore(3); @Override
public 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执行后的效果是:

三、CyclicBarrier

CyclicBarrier的功能如果用图来表示的话,就会是这样的:

CyclicBarrier实例代码:

/**
* 栅栏
*
* @author 湘王
*/
public class CyclicBarrierTester implements Runnable {
private final static CyclicBarrier barrier = new CyclicBarrier(3); @Override
public void run() {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " 已达到预定位置,等待指令...");
// 只有最后一个线程执行后,所有的线程才能执行2
barrier.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();
}
}

CyclicBarrier执行后的效果是:

四、Exchanger

Exchanger的功能如果用图来表示的话,就会是这样的:

Exchanger实例代码:

/**
* 交换机
*
* @author 湘王
*/
public class ExchangerTester implements Runnable {
Exchanger<Object> exchanger = null;
Object object = null; public ExchangerTester(Exchanger<Object> exchanger, Object object) {
this.exchanger = exchanger;
this.object = object;
} @Override
public void run() {
try {
Object previous = this.object;
this.object = this.exchanger.exchange(this.object);
System.out.println(Thread.currentThread().getName() + " 用对象 " + previous + " 换对象 " + this.object);
} catch (InterruptedException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
Exchanger<Object> exchanger = new Exchanger<Object>();
ExchangerTester tester1 = new ExchangerTester(exchanger, "A");
ExchangerTester tester2 = new ExchangerTester(exchanger, "B"); new Thread(tester1).start();
new Thread(tester2).start();
}
}

Exchanger执行后的效果是:

把这四种同步器掌握好(包括它们的组合使用),几乎可以解决90%以上的使用多线程的场景问题,再也不用担心不会多线程了。


感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~

Java多线程(7):JUC(上)的更多相关文章

  1. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  2. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  3. Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例

    概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...

  4. Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock

    本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...

  5. Java多线程系列--“JUC锁”01之 框架

    本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...

  6. Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例

    概要 前面对"独占锁"和"共享锁"有了个大致的了解:本章,我们对CountDownLatch进行学习.和ReadWriteLock.ReadLock一样,Cou ...

  7. Java多线程系列--“JUC锁”06之 Condition条件

    概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...

  8. Java多线程系列--“JUC锁”05之 非公平锁

    概要 前面两章分析了"公平锁的获取和释放机制",这一章开始对“非公平锁”的获取锁/释放锁的过程进行分析.内容包括:参考代码获取非公平锁(基于JDK1.7.0_40)释放非公平锁(基 ...

  9. Java多线程系列--“JUC锁”07之 LockSupport

    概述 本章介绍JUC(java.util.concurrent)包中的LockSupport.内容包括:LockSupport介绍LockSupport函数列表LockSupport参考代码(基于JD ...

  10. Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock

    概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...

随机推荐

  1. RabbitMQ实现订单超时案例

    前言 人间清醒 目录 前言 业务场景 JUC(DelayQueue)方案 DelayQueue简介 JUC DelayQueue实现订单超时案例代码 案例代码 Redis Key过期事件方案 简介 R ...

  2. 【Java】学习路径58-TCP聊天-双向发送实现

    这一章内容比较复杂(乱) 重点在于解决利用TCP协议实现双向传输. 其余的细节(比如end)等,不需要太在意. 但是我也把折腾经历写出来了,如果大家和我遇到了类似的问题,下文可以提供一个参考. 目标: ...

  3. DataGridVIew控件绑定数据之后的,增、插、删操作

    最开始没有绑定数据,很快就实现了增.插.删操作,可是绑定数据之后,进行这些操作就会报错. 网上对这方面的资料比较少,自己摸索着找到了解决方法,也就是直接对绑定的数据进行操作,这里以DataTable为 ...

  4. c++的一些笔记

    --const 的一些用法 1,修饰指针 const int *p=....   可以改变指针所指的位置,但不能改变指向位置的值. 2,修饰变量 int const * p=....  可以改变指向位 ...

  5. KingbaseES批量数据加载的实践技巧

    有时,KingbaseES数据库需要在单个或最少的步骤中导入大量数据,这通常称为批量数据导入.其中数据源通常是一个或多个大文件,这个过程有时可能非常慢. 造成性能不佳的原因有很多:索引.触发器.外键. ...

  6. 【读书笔记】C#高级编程 第十二章 动态语言扩展

    (一)DLR C#4的动态功能是Dynamic Language Runtime(动态语言运行时,DLR)的一部分.DLR是添加到CLR的一系列服务. (二)dynamic类型 dynamic类型允许 ...

  7. 坚守自主创新,璞华HawkEye IETM系统惠及国计民生

    可上九天揽月,可下五洋捉鳖,这是我们很多年的梦想.而要实现这样的梦想,不仅需要安全可靠的技术装备,还需要让这些技术装备处于良好的维保状态.于是,作为装备维保过程中必须的知识创作.管理.发布.浏览工具, ...

  8. [Python]-pandas模块-机器学习Python入门《Python机器学习手册》-03-数据整理

    <Python机器学习手册--从数据预处理到深度学习> 这本书类似于工具书或者字典,对于python具体代码的调用和使用场景写的很清楚,感觉虽然是工具书,但是对照着做一遍应该可以对机器学习 ...

  9. 若依(RuoYi )权限管理设计

    前言 若依权限管理包含两个部分:菜单权限 和 数据权限.菜单权限控制着我们可以执行哪些操作.数据权限控制着我们可以看到哪些数据. 菜单是一个概括性名称,可以细分为目录.菜单和按钮,以若依自身为例: 目 ...

  10. 4.云原生之Docker容器数据持久化介绍与实践

    转载自:https://www.bilibili.com/read/cv15182308/?from=readlist #### 创建一个web容器并创建一个数据卷挂载到容器的/webapp目录下(默 ...