Java多线程(7):JUC(上)
您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~
前面把线程相关的生命周期、关键字、线程池(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(上)的更多相关文章
- Java多线程系列--“JUC锁”03之 公平锁(一)
		
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
 - Java多线程系列--“JUC锁”04之 公平锁(二)
		
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
 - Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例
		
概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...
 - Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock
		
本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...
 - Java多线程系列--“JUC锁”01之 框架
		
本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...
 - Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例
		
概要 前面对"独占锁"和"共享锁"有了个大致的了解:本章,我们对CountDownLatch进行学习.和ReadWriteLock.ReadLock一样,Cou ...
 - Java多线程系列--“JUC锁”06之 Condition条件
		
概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...
 - Java多线程系列--“JUC锁”05之 非公平锁
		
概要 前面两章分析了"公平锁的获取和释放机制",这一章开始对“非公平锁”的获取锁/释放锁的过程进行分析.内容包括:参考代码获取非公平锁(基于JDK1.7.0_40)释放非公平锁(基 ...
 - Java多线程系列--“JUC锁”07之 LockSupport
		
概述 本章介绍JUC(java.util.concurrent)包中的LockSupport.内容包括:LockSupport介绍LockSupport函数列表LockSupport参考代码(基于JD ...
 - Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock
		
概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...
 
随机推荐
- 谈谈你对Promise的理解
			
一.Promise是什么? 理解 抽象表达: Promise 是一门新的技术(ES6 规范) Promise 是 JS 中进行异步编程的新解决方案(备注:旧方案是单纯使用回调函数) 具体表达: 从语法 ...
 - 如何保证遍历parent的时候的task的存在性
			
在一次crash的排查过程中,有这么一个内核模块,他需要往上遍历父进程, 但是在拿父进程task_struct中的一个成员的时候,发现为NULL了, 具体查看父进程,原来它收到信号退出中. 那么怎么保 ...
 - 2022CISCN-satool
			
2022CISCN-satool 打国赛的时候自己还并不了解LLVM PASS pwn,前几天正好学习了一下LLVM PASS pwn,于是就顺便来复现一下这道题目. 首先找到二进制文件的重写函数的主 ...
 - SUSE Linux Enterprise Server 12 使用二进制文件安装docker
			
Docker-CE in SUSE 虽然使用zypper添加源也能安装,不过我在SLES 12sp5 上安装时发现好多命令还需要自己手动软连接,干脆网上找了找文档,再自己小改下,用二进制部署,也是可以 ...
 - Windows 11 新材质 Mica Alt 效果展示
			
本文是 WinUI 3 踩坑记 的一部分,该系列发布于 GitHub@Scighost/WinUI3Keng,若内容出现冲突以 GitHub 上的为准. 微软在 2022-09-02 更新了官方文档, ...
 - 【疑难杂症】关于用pydotplus生成iris.pdf报错问题
			
在使用刘建平老师博客中DecisionTreeClassifier实例时,遇到报错:InvocationException: GraphViz's executables not found 源代码如 ...
 - Prometheus 监控 Kubernetes Job 资源误报的坑
			
转载自:https://www.qikqiak.com/post/prometheus-monitor-k8s-job-trap/ 昨天在 Prometheus 课程辅导群里面有同学提到一个问题,是关 ...
 - 云服务器 Centos7 部署 Elasticsearch 8.0 + Kibana 8.0 指南
			
文章转载自:https://mp.weixin.qq.com/s/iPfh9Mkwxf5lieiqt6ltxQ 服务器是命令行模式登录,没法以浏览器方式访问.而官方推荐的快捷部署方式,在kibana ...
 - Elastic:使用Grafana监视 Elasticsearch
 - spring boot http status 400
			
SpringBootAdmin不是Spring官方提供的模块,它包含了Client和Server两部分.server部分提供了用户管理界面,client即为被监控的服务.client需要注册到serv ...