java.util.concurrent.*下的常见类你了解多少?
java.util.concurrent.*是标准库提供的一组工具类,帮我们简化并发编程
1.concurrent下的locks锁
1.1.locks锁下常见的锁
![在这里插入图片描述](https://img-blog.csdnimg.cn/b9bd751d7875497ba5693a76c5da8025.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3draDE4ODkxODQzMTY1,size_16,color_FFFFFF,t_70)
1.2.lock和sychronized的之间的区别
- lock锁的加锁和解锁操作是分开的
- lock体系是Java语言层面实现的,sychronized是JVM实现的
- lock提供了一些更灵活的方法(如trylock,如果尝试获取失败就直接放弃,或等待指定等待时间再放弃)
大部分情况下还是在使用sychronized,特殊情况下载使用其他锁,如果是自定制的锁,那么就需要lock系列
2.concurrent.atomic下的原子类
如:AtomicInterger
public class Test{public static AtomicInteger num = new AtomicInteger(0);public static void main(String[] args) {//1.获取值int ret = num.get();//2.修改值num.set(100);//3.进行自增/自减int num1 = num.getAndIncrement(); // n++int num2 = num.incrementAndGet(); // ++n}
}
3.concurrent下的Callable
通常Callable/Future/FutureTask是搭配使用的,就是把线程封装成了能够返回结果的样子,我们之前创建的Thread都是没有返回值的,如果想多线程进行一些计算,就需要自己来汇总
上代码
如:求1—100的和
/*** Callable和Runnable很像,都是来描述一个具体的“任务”,* 但是Runnable是没有返回值的,而Callable是有返回值的*/
public class Test{public static void main(String[] args) throws ExecutionException, InterruptedException {//1.创建CallableCallable<Integer> callable = new Callable<Integer>() {@Overridepublic Integer call() throws Exception {//实现call方法,来求值int num = 0;for (int i = 0; i <= 100; i++) {num += i;}return num;}};//2.创建一个FutureTaskFutureTask<Integer> futureTask = new FutureTask<>(callable);//3.创建一个个线程Thread thread = new Thread(futureTask);thread.start();//4.获取线程执行结果,get方法会发生阻塞,一直到call方法执行完毕,get方法才会返回Integer integer = futureTask.get();System.out.println(integer);}
}
如果创建的线程不需要返回值,就可以使用Runnable,如果需要返回值,就可以使用Callable(搭配Future或者FutureTask使用)。因为Thread里面没有直接获取结果的方法
4.Semaphore(信号量)
相当于一个“计数器”,表示当前可用资源的个数
每次有人申请一个资源,信号量的值就+1(P操作)
每次有人释放一个资源,信号量的值就 -1(V操作)
当信号量的值为0的时候,那么此时就有两种策略:1.等待直到有人释放资源;2.不再等待,去找其他的资源
多线程在进行·PV操作的时候,此时线程都是安全的(信号量计数加减都是原子的)
信号量中有一个特殊的情况,当信号量的值只有0和1两种取值的时候,这种成为“二元信号量”,所谓的“二元信号量”本质上就是一个互斥锁(synchronized就可以视为一个“二元信号量”,同一时刻一个线程能获取到锁,相当于资源为1)
比如:停车场就会有一个计数器,门口就会有一个显示牌,上面显示还剩下多少车位,每当有车进入停车场,计数就-1,每当有人开出停车场,计数牌就+1,但是如果此时停车位为0的时候,在当有人进来,此时有两种情况:要么等待里面有人开出来,要么扭头就走,去找其他停车场
上代码
public class Test{public static void main(String[] args){//表示可用资源的个数Semaphore semaphore = new Semaphore(5);Runnable runnable = new Runnable() {@Overridepublic void run() {try {long threadId = Thread.currentThread().getId();System.out.println("申请资源:"+threadId);//P 操作申请资源,计数器就-1semaphore.acquire();System.out.println("我获取到资源了:"+threadId);Thread.sleep(1000);System.out.println("我释放资源了:"+threadId);//释放资源,计数器就+1semaphore.release();} catch (InterruptedException e) {e.printStackTrace();}}};//创建20个线程去获取这5个资源for (int i = 0; i < 20; i++) {Thread thread = new Thread(runnable);thread.start();}}
}
执行结果
在有多个共享资源的时候,就可以使用信号量(比如实现一个线程安全的阻塞队列)
5.线程池ThreadPoolExecutor
线程池系列相关的类还有Executors,ExecutorService
线程池存在的意义,就是为了频繁创建/销毁线程的开销
面试常考:线程池构造方法里面的参数含义
corePoolSize:核心线程数大小,当线程数<corePoolSize ,会创建线程执行runnable
maximumPoolSize: 最大线程数, 当线程数 >= corePoolSize的时候,会把runnable放入workQueue中
keepAliveTime:保持存活时间,当线程数大于corePoolSize的空闲线程能保持的最大时间。
unit :时间单位
workQueue: 保存任务的阻塞队列
threadFactory :创建线程的工厂
handler :拒绝策略
任务执行顺序:
1、当线程数小于corePoolSize时,创建线程执行任务。
2、当线程数大于等于corePoolSize并且workQueue没有满时,放入workQueue中
3、线程数大于等于corePoolSize并且当workQueue满时,新任务新建线程运行,线程总数要小于maximumPoolSize
4、当线程总数等于maximumPoolSize并且workQueue满了的时候执行handler的rejectedExecution。也就是拒绝策略。
拒绝策略
1、ThreadPoolExecutor.AbortPolicy() 直接抛出异常RejectedExecutionException
2、ThreadPoolExecutor.CallerRunsPolicy() 直接调用run方法并且阻塞执行
3、ThreadPoolExecutor.DiscardPolicy() 直接丢弃后来的任务
4、ThreadPoolExecutor.DiscardOldestPolicy() 丢弃在队列中队首的任务
6.CountDownLatch
好像跑步比赛,10个选手依次就位,哨声响才同时出发;所有选手都通过终点,才能公布成绩。
public class Test{public static void main(String[] args) throws InterruptedException {//表示有10个选手CountDownLatch countDownLatch = new CountDownLatch(10);Runnable runnable = new Runnable() {@Overridepublic void run() {try {Thread.sleep(1000);//某个选手到达终点countDownLatch.countDown();} catch (InterruptedException e) {e.printStackTrace();}}};for (int i = 0; i < 10; i++) {new Thread(runnable).start();}//必须要等到10人全部到达终点,await才会返回,否则就会阻塞countDownLatch.await();System.out.println("比赛结束");}
}
还比如:下载一个1G大小的文件,就可以分成10个线程,每个线程负责100MB,等待10个线程下载完,这个文件才算下载完成
面试常考
- Thread,Runnable,Callable之间的区别和联系
- 线程同步的方式有哪些?
- 你平时用过哪些线程同步的方式?
- 为什么有了 synchronized 还需要 juc (java.util.concurrent)下的 lock?
- AtomicInteger 的实现原理是什么?
- 信号量听说过么?之前都用在过哪些场景下?
- 说一下并发包下有哪些并发类,concurrentHashmap,unsafe,原子类,都分别讲一下怎么支持并发 的?
java.util.concurrent.*下的常见类你了解多少?相关推荐
- 【JDK源码】java.util.concurrent.atomic包常用类详解
java.util.concurrent.atomic原子操作类包里面提供了一组原子变量类.其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当某个线程进入方 ...
- java.util.concurrent.atomic原子操作类包
2019独角兽企业重金招聘Python工程师标准>>> 这个包里面提供了一组原子变量类.其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当 ...
- java.util.concurrent包详细分析--转
原文地址:http://blog.csdn.net/windsunmoon/article/details/36903901 概述 Java.util.concurrent 包含许多线程安全.测试良好 ...
- 【Java】JUC(java.util.concurrent)工具包中的并发相关
目录 一.AQS详解 AQS原理 AQS 对资源的共享方式 AQS 底层使用了模板方法模式 AQS具体应用举例 ReentrantLock CountDownLatch 二.ConcurrentHas ...
- java.util.concurrent介绍
为什么80%的码农都做不了架构师?>>> java.util.concurrent 包含许多线程安全.测试良好.高性能的并发构建块.不客气地说,创建 java.util.con ...
- java.util.concurrent介绍【转】
java.util.concurrent介绍 java.util.concurrent 包含许多线程安全.测试良好.高性能的并发构建块.不客气地说,创建 java.util.concurrent 的目 ...
- Java 并发 —— Java 标准库对并发的支持及 java.util.concurrent 包
0. Collections.synchronizedXxx() Java 中常用的集合框架中的实现类:HashSet/TreeSet.ArrayList/LinkedList.HashMap/Tre ...
- 高并发编程基础(java.util.concurrent包常见类基础)
JDK5中添加了新的java.util.concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全性,所以这种方法 ...
- 【JAVAEE】JUC(java.util.concurrent)的常见类
目录 1.Callable接口 1.1简介 1.2代码演示 1.3Runnable与Callable的区别 2.ReentrantLock 2.1ReentrantLock的常用方法 2.2Reent ...
最新文章
- 手机内存RAM、ROM简介
- 使用Tensorflow实现残差网络ResNet-50
- Java连载2-Java特性
- 【机器学习】基于opencv实现目标检测,error LNK2001: unresolved external symbol public: virtual bool CvSVM::train...
- C++ dlopen mini HOWTO 一篇非常好的介绍C++ dlopen linux/mac os x 编程的资料
- java jsp ajax_ajax的json传值方式在jsp页面中的应用
- glassfish服务器默认的网页所在的位置
- munin mysql_munin 监控 mysql 2种方法
- mysql shell可视化_shell编程系列24--shell操作数据库实战之利用shell脚本将文本数据导入到mysql中...
- PL/SQL面向过程语言
- python的for语句要用冒号吗_python中循环的写法 for
- audio realtek 耳机没声_window7和window10机箱前面板耳机插孔没有声音怎么解决!
- 带外设引脚选择(PPS)的I/O端口
- 修改VS2017密钥
- Kafka Consumer 消费逻辑
- Telephone--短信发送/接收流程
- cs231n-assignment3的笔记
- 【Activity学习五】--基于SSM整合Activiti之请假流程实现(二)
- js算法---寻找连续数组中的缺失数
- 机器学习实战——决策树(代码)
热门文章
- Sphinx sphinx_rtd_theme
- matplotlib text 文字处理
- R语言高级算法之人工神经网络(Artificial Neural Network)
- 指针 | golang之指针的学习
- Docker学习总结(37)——Dockerfile编写的八条准则
- Ehcache学习总结(1)--Ehcache入门介绍
- WebService学习总结(三)——使用JDK开发WebService
- python之设计模式的装饰器9步学习
- Android ActionBarSherlock使用教程
- APICloud App定制平台的操作指南