【待完成】并发包下常用到线程工具类汇总

文章目录

  • 并发容器
    • BlockingQueue
      • ArrayBlockingQueue
      • LinkedBlockingQueue
      • PriorityBlocking
      • DelayQueue
      • SynchronousQueue
    • BlockingDeque
    • CopyOnWrite
      • CopyOnWriteArrayList
      • CopyOnWriteArraySet
    • ConcurrentLinkedQueue/Deque
    • ConcurrentHashMap
    • ConcurrentSkipListMap/Set
  • 同步工具类
    • AQS实现类
      • CountDownLatch
      • CyclicBarrier
      • Semaphore
      • ReentrantLock
      • ReentrantLockReadWriteLock
      • ThreadPoolExecutor
    • Exchanger
    • Phaser
  • Atomic类
    • AtomicInteger和AtomicLong
    • AtomicBoolean和AtomicReference
    • AtomicStampedReference和AtomicMarkableReference
    • AtomicIntegerFieldUpdater、AtomicLongFieldUpdater和AtomicReferenceFieldUpdater
    • AtomicIntegerArray、AtomicLongArray和AtomicReferenceArray
    • Striped64和LongAdder
  • Lock和Condition
    • 互斥锁
    • 读写锁
    • Condition
    • StampedLock

并发容器

BlockingQueue

ArrayBlockingQueue

LinkedBlockingQueue

PriorityBlocking

DelayQueue

SynchronousQueue

BlockingDeque

CopyOnWrite

CopyOnWriteArrayList

CopyOnWriteArraySet

ConcurrentLinkedQueue/Deque

ConcurrentHashMap

ConcurrentSkipListMap/Set

同步工具类

AQS实现类

AQS是一个用于构建锁、同步器等线程协作工具类的框架,有了AQS后,很多用于线程协作的工具类都可以很方便的被写出来

内部使用了AQS(AbstractQueuedSynchronizer)下的工具类

  1. CountDownLatch(CyclicBarrier->ReentrantLock->AQS)
  2. Semaphore
  3. ThreadPoolExecutor
  4. ReentrantLock
  5. ReentrantLockReadWriteLock

在这里插入图片描述
一下介绍各个工具类的使用(源码部分,等看完后,后续补充详细说明

CountDownLatch

作用:计数器

源码
在这里插入图片描述

实战

作用一:一个线程等待其他多个线程都执行完毕,再继续自己的工作:

    @Testpublic void countdownlatchTest() throws InterruptedException {final CountDownLatch countDownLatch = new CountDownLatch(5);ExecutorService threadPool = Executors.newFixedThreadPool(5);for (int i = 0; i < 5; i++) {final int finalI = i;threadPool.submit(new Runnable() {@Overridepublic void run() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(finalI + "开始跑步!");//把倒数值-1,那么之前awiat等待的线程会被唤醒countDownLatch.countDown();}});}System.out.println("等待5个运动员都跑完");//调用await方法的线程开始等待,直到倒数结束countDownLatch.await();System.out.println("所有人都跑完了,比赛结束");}

在这里插入图片描述

作用二:多个线程等待某一个线程的信号,同时开始执行

    @Testpublic void countdownlatch2() throws InterruptedException {ExecutorService threadPool = Executors.newFixedThreadPool(5);final CountDownLatch countDownLatch = new CountDownLatch(1);for (int i = 0; i < 5; i++) {final int finalI = i;threadPool.submit(new Runnable() {@Overridepublic void run() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(finalI + "ready");try {countDownLatch.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(finalI + "run");}});}Thread.sleep(5000);System.out.println("start run!");countDownLatch.countDown();}

在这里插入图片描述

CyclicBarrier

源码

在这里插入图片描述
从源码中可以看出,CyclicBarrier利用可重入锁ReentrantLock和Condition
实战

CyclicBarrier构造出一个集结点,当某一个线程执行await()当时候,它就会到这个集结点开始等待,等待达到预定值等待到线程就会统一出发

    public void cyclicBarrierTest() throws InterruptedException {CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() {@Overridepublic void run() {System.out.println("集结完毕,准备出发");}});//重复利用for (int i = 0; i < 6; i++) {new Thread(new Task(i, cyclicBarrier)).start();}Thread.sleep(1000 * 100000);}class Task implements Runnable {private int id;private CyclicBarrier cyclicBarrier;public Task(int i, CyclicBarrier cyclicBarrier) {this.id = i;this.cyclicBarrier = cyclicBarrier;}@Overridepublic void run() {System.out.println("同学" + id + "现在从大门出发");try {Thread.sleep((long) (Math.random() * 1000));System.out.println("同学" + id + "到了自行车驿站,开始等待其他人到达");cyclicBarrier.await();System.out.println("同学" + id + "开始骑车");} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}}

在这里插入图片描述

Semaphore

信号量用来控制需要限制并发访问量的资源

源码
在这里插入图片描述
在这里插入图片描述
实战

    @Testpublic void semaphoreTest() throws Exception {final Semaphore semaphore = new Semaphore(2);ExecutorService executorService = Executors.newFixedThreadPool(1000);for (int i = 0; i < 1000; i++) {final int finalI = i;executorService.submit(new Runnable() {@Overridepublic void run() {try {semaphore.acquire();Thread.sleep(3000);System.out.println(finalI + "run");} catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release();}System.out.println("--------");}});}Thread.sleep(1000 * 100000);}

ReentrantLock

源码
在这里插入图片描述
在这里插入图片描述
实战
未使用锁情况:出现线程安全问题

    @Testpublic void ReentrantLockTest() {ReentrantLock lock = new ReentrantLock();CountDownLatch countDownLatch = new CountDownLatch(1);//模拟10个并发for (int i = 0; i < 10; i++) {final int n = i;new Thread(new Runnable() {@Overridepublic void run() {System.out.println(n + " 线程变成运行状态,等待命令");try {countDownLatch.await();/*** tryLock的方法就是试一下,如果能得到锁,就返回真,如果当时得不到,马上就返回假,绝不等。tryLock(时间)的用法就是 在规定的时间内设法得到锁。如果在规定的时间内最终不能得到锁,就返回假。* tryLock()方法只有在成功获取了锁的情况下才会返回true,如果别的线程当前正持有锁,则会立即返回false*/
//                        while (!lock.tryLock()) ;compute(n);} catch (InterruptedException e) {e.printStackTrace();} finally {
//                        lock.unlock();}}}).start();}try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程创建完毕,准备计数!");countDownLatch.countDown();try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("计数结果:" + k);}private void compute(int n) {for (int j = 0; j < 10000; j++) {if (n % 2 == 0) {k--;} else {k++;}}}

在这里插入图片描述

采用锁情况:返回结果为0,没有线程安全问题

    @Testpublic void ReentrantLockTest() {ReentrantLock lock = new ReentrantLock();CountDownLatch countDownLatch = new CountDownLatch(1);//模拟10个并发for (int i = 0; i < 10; i++) {final int n = i;new Thread(new Runnable() {@Overridepublic void run() {System.out.println(n + " 线程变成运行状态,等待命令");try {countDownLatch.await();/*** tryLock的方法就是试一下,如果能得到锁,就返回真,如果当时得不到,马上就返回假,绝不等。tryLock(时间)的用法就是 在规定的时间内设法得到锁。如果在规定的时间内最终不能得到锁,就返回假。* tryLock()方法只有在成功获取了锁的情况下才会返回true,如果别的线程当前正持有锁,则会立即返回false*/while (!lock.tryLock()) ;compute(n);} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}}).start();}try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程创建完毕,准备计数!");countDownLatch.countDown();try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("计数结果:" + k);}private void compute(int n) {for (int j = 0; j < 10000; j++) {if (n % 2 == 0) {k--;} else {k++;}}}

在这里插入图片描述

ReentrantLockReadWriteLock

多线程情况下:读-写互斥、写-读互斥、写-写互斥、读-读共享
使用场景:
对于数据比较敏感的场景,
读锁:在读取数据时是不能出现多次读取不一致的情况的,这点有点像可重复读和幻读,
写锁:写数据时,又不能同时读取数据

 参考博客:https://www.cnblogs.com/zxporz/p/10874853.html

源码
在这里插入图片描述

实战

   private final Map<String, Integer> map = new TreeMap<>();private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();private final Lock readLock = lock.readLock();private final Lock writeLock = lock.writeLock();public Integer get(String key) {readLock.lock();try {return map.get(key);} finally {readLock.unlock();}}public Set<String> allKeys() {readLock.lock();try {return map.keySet();} finally {readLock.unlock();}}public Integer put(String key, Integer value) {writeLock.lock();try {return map.put(key, value);} finally {writeLock.unlock();}}public void clear() {writeLock.lock();try {map.clear();} finally {writeLock.unlock();}}

ThreadPoolExecutor

用来构建线程池

源码
在这里插入图片描述
在这里插入图片描述
实战

    @Testpublic void threadpoolExcutorTest() throws ExecutionException, InterruptedException {ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10),new ThreadPoolExecutor.DiscardOldestPolicy());/*** 模拟20个并发,3个核心线程数、最大线程数5个,阻塞队列容量为10,* 此时处理流程?** 取决于用何种拒绝策略* 1.如果用到是默认拒绝策略:AbortPolicy 此时程序直接抛出RejectedExecutionException到RuntimeException异常,* 为unchecked异常,如果不手动捕获程序就会异常退出* java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@64a294a6* rejected from java.util.concurrent.ThreadPoolExecutor@7e0b37bc[Running, pool size = 5, active threads = 5, queued tasks = 10, completed tasks = 0]* 2.如果是DiscardPolicy:新任务提交后直接被丢弃了,也不会给你任何到通知* 0-thread run* 1-thread run* 2-thread run* 3-thread run* 4-thread run* 5-thread run* 6-thread run* 7-thread run* 8-thread run* 9-thread run* 10-thread run* 11-thread run* 12-thread run* 13-thread run* 14-thread run* 3.如果是DiscardOldestPolicy,丢弃任务队列中到头节点,通常是存活时间最长到任务,存在数据丢失风险* 0-thread run* 1-thread run* 2-thread run* 4.如果是CallerRunsPolicy,当有新任务提交后,如果线程池没被关闭且没有能力执行,则把这个任务交给提交任务到线程去执行* 0-thread run* 1-thread run* 2-thread run* 3-thread run* 4-thread run* 5-thread run* 6-thread run* 7-thread run* 8-thread run* 9-thread run* 10-thread run* 11-thread run* 12-thread run* 13-thread run* 14-thread run* 15-thread run* 16-thread run* 17-thread run* 18-thread run* 19-thread run*/ArrayList<Future> futureList = new ArrayList<>(20);for (int i = 0; i < 20; i++){final int finalI = i;Future<String> future = threadPoolExecutor.submit(new Callable<String>() {@Overridepublic String call() throws Exception {Thread.sleep(1000);return finalI + "-thread run";}});futureList.add(future);}for (int i = 0; i < 20; i++){try {System.out.println(futureList.get(i).get(1000, TimeUnit.SECONDS));} catch (TimeoutException e) {e.printStackTrace();}}try {Thread.sleep(1000 * 10000);} catch (InterruptedException e) {e.printStackTrace();}}

Exchanger

Phaser

Atomic类

AtomicInteger和AtomicLong

AtomicBoolean和AtomicReference

AtomicStampedReference和AtomicMarkableReference

AtomicIntegerFieldUpdater、AtomicLongFieldUpdater和AtomicReferenceFieldUpdater

AtomicIntegerArray、AtomicLongArray和AtomicReferenceArray

Striped64和LongAdder

Lock和Condition

互斥锁

读写锁

Condition

StampedLock

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/508810.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

爬虫中如何获取页面编码类型

获取页面的编码格式的三种方式&#xff1a; 根据Response中的header获取编码格式根据页面标签中的meta获取根据页面内容识别自动识别出编码格式&#xff0c;经过测试准确率比较高 三种方式可以结合使用&#xff0c;由于inputStream不能够被复用&#xff0c;但是inputStrem没有…

Spark集群部署与架构

在大数据时代&#xff0c;处理海量数据需要分布式计算框架。Apache Spark作为一种强大的大数据处理工具&#xff0c;可以在集群中高效运行&#xff0c;处理数十TB甚至PB级别的数据。本文将介绍如何构建和管理Spark集群&#xff0c;以满足大规模数据处理的需求。 Spark集群架构…

java核心技术-多线程并发设计原理以及常见面试题

文章目录写在前面多线程回顾Thread和Runnable面试官&#xff1a;为什么我们在项目中推荐使用使用Runnable方法而不用继承Thread&#xff1f;面试官&#xff1a;Callable为什么可以带返回值&#xff0c;你知道底层原理&#xff1f;面试题&#xff1a;线程了解&#xff1f;给我讲…

java核心技术-jvm基础知识

文章目录JVM回顾JVM、JRE、JDK之间关系&#xff1f;Java程序执行过程&#xff1f;面试官&#xff1a;解释执行和JIT(及时编译)两种执行方式有什么区别&#xff1f;java虚拟机内存管理jvm整体架构JVM只是定义内存划分规范等&#xff0c;具体实现依赖不同虚拟机实现&#xff0c;如…

多线程场景下利用ThreadLocal是线程安全?

文章目录背景多线程场景测试代码结论背景 ThreadLocal原理以及基本概念这里我就不介绍了&#xff0c;这里我们主要关注ThreadLocal是否是线程安全吗&#xff1f;其实如果我们知道ThreadLocal原理我们肯定知道它是线程安全的&#xff0c;但是我在开发的时候不放心做了个测试&am…

深入剖析线程池基本原理以及常见面试题详解

文章目录面试官&#xff1a;能给我讲讲线程池的实现原理&#xff1f;线程池类继承关系ThreadPoolExecutor核心数据结构面试官&#xff1a;给我讲讲线程池的有哪些参数&#xff1f;面试官&#xff1a;如何优雅的关闭线程&#xff1f;线程的生命周期面试官&#xff1a;线程池哪五…

设计模式七大设计原则

文章目录设计模式七大设计原则开闭原则里氏替换原则依赖倒置原则接口隔离原则迪米特法则-最少知道原则单一职责原则合成复用原则设计模式 面向对象的三个基本特征&#xff1a; 继承封装多态 设计模式体现了代码的耦合性、内聚性、可维护性、可扩展性、重用性、灵活性。 代码…

从框架源码中学习结构型设计模式

文章目录从框架源码学习结构型设计模式适配器模式应用实例案例一&#xff1a;dubbo框架日志适配器Logger接口日志实现类Logger适配器接口LoggerAdapter实现类Logger日志工厂桥接模式应用场景案例&#xff1a;dubbo源码-远程调用模块channelHandler设计ChannelHandler是一个SPI拓…

MDC日志logback整合使用

MDC日志logback整合使用 为什么使用MDC记录日志&#xff1f; 场景&#xff1a; 由于我的搜索服务并发量比较高&#xff0c;而处理一次搜索请求需要记录多个日志&#xff0c;因此日志特别多的情况下去查一次搜索整个日志打印情况会比较复杂。 解决方案&#xff1a; 可以使用用…

如何合理的配置线程数?

文章目录题记Java并发编程实战美团技术团队追求参数设置合理性线程池参数动态化题记 我想不管是在面试中、还是工作中&#xff0c;我们总会面临这种问题&#xff0c;那么到底有没有一种计算公式去告诉我们如何去配置呢&#xff1f; 答案是&#xff1a;没有 想要合理的配置线…

基于CompletableFuture并发任务编排实现

文章目录并发任务编排实现不带返回值/参数传递任务串行执行并行执行并行执行-自定义线程池阻塞等待&#xff1a;多并行任务执行完再执行任意一个任务并发执行完就执行下个任务串并行任务依赖场景带返回值/参数传递任务带返回值实现串行执行多线程任务串行执行对任务并行执行&am…

搜索研发工程师需要掌握的一些技能

文章目录基础语言数据结构与算法工程方面搜索相关搜索主要模块电商搜索流程分词相关搜索召回相似度算法相关词推荐排序相关国美搜索搜索算法工程师需要掌握的技能基础 语言 大部分公司用的是Solr、ElasticSearch&#xff0c;都是基于Java实现的&#xff0c;因此熟悉掌握Java语…

Flink入门看完这篇文章就够了

文章目录第一章&#xff1a;概述第一节&#xff1a;什么是Flink&#xff1f;第二节&#xff1a;Flink特点&#xff1f;第三节&#xff1a;Flink应用场景&#xff1f;第四节&#xff1a;Flink核心组成第五节&#xff1a;Flink处理模型&#xff1a;流处理和批处理第六节&#xff…

word小结

域代码/域结果显示设置 word选项---->>高级------>>显示域代码而非域值将样式传给其它文件使用 首先启动Word打开包含这些样式的一个文件&#xff0c;然后选择“工具”---->“模板和加载项”。在弹出的对话框中单击“管理器”按钮。在弹出的“管理器”对话框中&…

线程属性总结

今天面试那哥们问起线程属性&#xff0c;me竟然就说出了一个&#xff0c;囧 学习&#xff1a;http://blog.csdn.net/zsf8701/article/details/7842392 http://blog.csdn.net/jxhnuaa/article/details/3254299 http://blog.sina.com.cn/s/blog_9bd573450101hgdr.html int pthre…

百度2015校园招聘软件开发笔试题及答案

简单题&#xff08;本题共30分&#xff09; 请简述Tcp-ip的3次握手以及4次挥手过程&#xff1f;并解释为何关闭连接需要4次挥手(10分) 详细答案参见TCP/IP协议三次握手与四次握手流程解析 TCP三次握手、四次挥手过程如下: 通常情况下&#xff0c;一个正常的TCP连接&#xf…

linux ps 命令使用

Linux中的ps命令是Process Status的缩写。ps命令用来列出系统中当前运行的那些进程。ps命令列出的是当前那些进程的快照&#xff0c;就是执行ps命令的那个时刻的那些进程&#xff0c;如果想要动态的显示进程信息&#xff0c;就可以使用top命令。 linux上进程有5种状态 ps命令使…

UML序列图总结

序列图主要用于展示对象之间交互的顺序。 序列图将交互关系表示为一个二维图。纵向是时间轴&#xff0c;时间沿竖线向下延伸。横向轴代表了在协作中各独立对象的类元角色。类元角色用生命线表示。当对象存在时&#xff0c;角色用一条虚线表示&#xff0c;当对象的过程处于激活…

UML用例图总结

用例图主要用来描述 用户、需求、系统功能单元 之间的关系。它展示了一个外部用户能够观察到的系统功能模型图。 【用途】&#xff1a;帮助开发团队以一种可视化的方式理解系统的功能需求。 用例图所包含的元素如下&#xff1a; 1. 参与者(Actor) 表示与您的应用程序或…