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的之间的区别

  1. lock锁的加锁和解锁操作是分开的
  2. lock体系是Java语言层面实现的,sychronized是JVM实现的
  3. 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个线程下载完,这个文件才算下载完成

面试常考

  1. Thread,Runnable,Callable之间的区别和联系
  2. 线程同步的方式有哪些?
  3. 你平时用过哪些线程同步的方式?
  4. 为什么有了 synchronized 还需要 juc (java.util.concurrent)下的 lock?
  5. AtomicInteger 的实现原理是什么?
  6. 信号量听说过么?之前都用在过哪些场景下?
  7. 说一下并发包下有哪些并发类,concurrentHashmap,unsafe,原子类,都分别讲一下怎么支持并发 的?

java.util.concurrent.*下的常见类你了解多少?相关推荐

  1. 【JDK源码】java.util.concurrent.atomic包常用类详解

    java.util.concurrent.atomic原子操作类包里面提供了一组原子变量类.其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当某个线程进入方 ...

  2. java.util.concurrent.atomic原子操作类包

    2019独角兽企业重金招聘Python工程师标准>>> 这个包里面提供了一组原子变量类.其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当 ...

  3. java.util.concurrent包详细分析--转

    原文地址:http://blog.csdn.net/windsunmoon/article/details/36903901 概述 Java.util.concurrent 包含许多线程安全.测试良好 ...

  4. 【Java】JUC(java.util.concurrent)工具包中的并发相关

    目录 一.AQS详解 AQS原理 AQS 对资源的共享方式 AQS 底层使用了模板方法模式 AQS具体应用举例 ReentrantLock CountDownLatch 二.ConcurrentHas ...

  5. java.util.concurrent介绍

    为什么80%的码农都做不了架构师?>>>    java.util.concurrent 包含许多线程安全.测试良好.高性能的并发构建块.不客气地说,创建 java.util.con ...

  6. java.util.concurrent介绍【转】

    java.util.concurrent介绍 java.util.concurrent 包含许多线程安全.测试良好.高性能的并发构建块.不客气地说,创建 java.util.concurrent 的目 ...

  7. Java 并发 —— Java 标准库对并发的支持及 java.util.concurrent 包

    0. Collections.synchronizedXxx() Java 中常用的集合框架中的实现类:HashSet/TreeSet.ArrayList/LinkedList.HashMap/Tre ...

  8. 高并发编程基础(java.util.concurrent包常见类基础)

    JDK5中添加了新的java.util.concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全性,所以这种方法 ...

  9. 【JAVAEE】JUC(java.util.concurrent)的常见类

    目录 1.Callable接口 1.1简介 1.2代码演示 1.3Runnable与Callable的区别 2.ReentrantLock 2.1ReentrantLock的常用方法 2.2Reent ...

最新文章

  1. 手机内存RAM、ROM简介
  2. 使用Tensorflow实现残差网络ResNet-50
  3. Java连载2-Java特性
  4. 【机器学习】基于opencv实现目标检测,error LNK2001: unresolved external symbol public: virtual bool CvSVM::train...
  5. C++ dlopen mini HOWTO 一篇非常好的介绍C++ dlopen linux/mac os x 编程的资料
  6. java jsp ajax_ajax的json传值方式在jsp页面中的应用
  7. glassfish服务器默认的网页所在的位置
  8. munin mysql_munin 监控 mysql 2种方法
  9. mysql shell可视化_shell编程系列24--shell操作数据库实战之利用shell脚本将文本数据导入到mysql中...
  10. PL/SQL面向过程语言
  11. python的for语句要用冒号吗_python中循环的写法 for
  12. audio realtek 耳机没声_window7和window10机箱前面板耳机插孔没有声音怎么解决!
  13. 带外设引脚选择(PPS)的I/O端口
  14. 修改VS2017密钥
  15. Kafka Consumer 消费逻辑
  16. Telephone--短信发送/接收流程
  17. cs231n-assignment3的笔记
  18. 【Activity学习五】--基于SSM整合Activiti之请假流程实现(二)
  19. js算法---寻找连续数组中的缺失数
  20. 机器学习实战——决策树(代码)

热门文章

  1. Sphinx sphinx_rtd_theme
  2. matplotlib text 文字处理
  3. R语言高级算法之人工神经网络(Artificial Neural Network)
  4. 指针 | golang之指针的学习
  5. Docker学习总结(37)——Dockerfile编写的八条准则
  6. Ehcache学习总结(1)--Ehcache入门介绍
  7. WebService学习总结(三)——使用JDK开发WebService
  8. python之设计模式的装饰器9步学习
  9. Android ActionBarSherlock使用教程
  10. APICloud App定制平台的操作指南