JUC并发编程之Callable接口、JUC三大辅助类
目录
8. Callable接口
8.1 创建线程的多种方式
8.2 概述
8.3 用Callable接口创建Thred线程
8.4 小结(重点)
9. JUC 三大辅助类
9.1 概述
9.2 减少计数 CountDownLatch
9.3 循环栅栏 CyclicBarrier
9.4 信号灯 Semaphore
8. Callable接口
8.1 创建线程的多种方式
- 继承Thread类
- 实现Runnable接口
- Callable接口
- 线程池
8.2 概述
目前我们学习了有两种创建线程的方法一种是通过创建 Thread 类,另一种是 通过使用 Runnable 创建线程。但是,Runnable 缺少的一项功能是,当线程 终止时(即 run()完成时),我们无法使线程返回结果。为了支持此功能, Java 中提供了 Callable 接口。
==现在我们学习的是创建线程的第三种方案---Callable 接口==
Callable 接口的特点如下(重点)
Runnable的 run()的方法没有返回值、不能产生异常
实现 Callable 而必须重写 call() 方法
- 有返回值:需要返回 call()方法的结果。
- 可以引发异常。
• 不能直接替换 runnable,因为 Thread 类的构造方法根本没有 Callable
// 创建新类 MyThread 实现 runnable 接口
class MyThread implements Runnable{@Overridepublic void run() {}
}
// 新类 MyThread2 实现 callable 接口
class MyThread2 implements Callable<Integer>{@Overridepublic Integer call() throws Exception {return 200;}}
• 不能直接替换 runnable,因为 Thread 类的构造方法根本没有 Callable
8.3 用Callable接口创建Thred线程
找一个类,既和Runnable有关系,又和Callable也有关系
- Runnbale接口有实现类:FutureTask
- FutureTask构造可以传递Callable
Runnable接口有实现类FutureTask(中间对象)
FutureTask的构造函数有Callable参数,通过FutureTask创建线程对象
public class CallableDemo {public static void main(String[] args) throws ExecutionException, InterruptedException{new Thread(()->{System.out.println(Thread.currentThread().getName()+"执行Runnable");}).start();FutureTask<String> task = new FutureTask<>(() -> {System.out.println(Thread.currentThread().getName() + "使用Callable接口");return "Callable接口的返回值";});new Thread(task).start();System.out.println("Callable返回值:" + task.get());}
}
8.4 小结(重点)
• 在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些 作业交给 Future 对象在后台完成, 当主线程将来需要时,就可以通过 Future 对象获得后台作业的计算结果或者执行状态。
• 一般 FutureTask 多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。
• 仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞 get 方法。一旦计 算完成,就不能再重新开始或取消计算。get 方法而获取结果只有在计算完成 时获取,否则会一直阻塞直到任务转入完成状态,然后会返回结果或者抛出异常。
9. JUC 三大辅助类
9.1 概述
JUC 中提供了三种常用的辅助类,通过这些辅助类可以很好的解决线程数量过多时 Lock 锁的频繁操作。这三种辅助类为:
• CountDownLatch: 减少计数
• CyclicBarrier: 循环栅栏
• Semaphore: 信号灯
9.2 减少计数 CountDownLatch
CountDownLatch类可以设置一个计数器,然后通过 countDown 方法来进行 减 1 的操作,使用 await 方法等待计数器不大于 0,然后继续执行 await 方法之后的语句。
- CountDownLatch 主要有两个方法,当一个或多个线程调用 await 方法时,这些线程会阻塞
- 其它线程调用 countDown 方法会将计数器减 1(调用 countDown 方法的线程不会阻塞)。
- 当计数器的值变为 0 时,因 await 方法阻塞的线程会被唤醒,继续执行。
public class CountDownLatchDemo {/*** 6 个同学陆续离开教室后值班同学才可以关门* @param args*/public static void main(String[] args) throws Exception{//定义一个数值为 6 的计数器CountDownLatch countDownLatch = new CountDownLatch(6);//创建 6 个同学for (int i = 1; i <= 6; i++) {new Thread(() ->{try{if(Thread.currentThread().getName().equals("同学 6")){Thread.sleep(2000);}System.out.println(Thread.currentThread().getName() + "离开了");//计数器减一,不会阻塞countDownLatch.countDown();}catch (Exception e){e.printStackTrace();}}, "同学 " + i).start();}//主线程 await 休息countDownLatch.await();//全部离开后自动唤醒主线程System.out.println("全部离开了,现在的计数器为" + countDownLatch.getCount());}
}
执行效果:
由于异步,使用CountDownLatch 来保证“同步”的
//定义一个数值为 6 的计数器 CountDownLatch countDownLatch = new CountDownLatch(6);
// 主线程堵塞
countDownLatch.await();
9.3 循环栅栏 CyclicBarrier
由英文单词可以看出大概就是循环阻塞的意思,在使用中 CyclicBarrier 的构造方法第一个参数是目标障碍数,每次执行 CyclicBarrier 一次障碍数会加一,如果达到了目标障碍数,才会执行 cyclicBarrier.await()之后 的语句。可以将 CyclicBarrier 理解为加 1
操作 场景: 集齐 7 颗龙珠就可以召唤神龙 (达到七个阻塞的线程就执行复活愿望)
public class CyclicBarrierDemo {//定义神龙召唤需要的龙珠总数private final static int NUMBER = 7;/*** 集齐 7 颗龙珠就可以召唤神龙* @param args*/public static void main(String[] args) {//定义循环栅栏CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER, () ->{System.out.println("集齐" + NUMBER + "颗龙珠,现在召唤神龙!!!!!!!!!");});//定义 7 个线程分别去收集龙珠for (int i = 1; i <= 7; i++) {new Thread(()->{try {if(Thread.currentThread().getName().equals("龙珠 3 号")){System.out.println("龙珠 3 号抢夺战开始,孙悟空开启超级赛亚人模 式!");Thread.sleep(5000);System.out.println("龙珠 3 号抢夺战结束,孙悟空打赢了,拿到了龙珠 3
号!");}else{System.out.println(Thread.currentThread().getName() + "收集到
了!!!!");}cyclicBarrier.await();}catch (Exception e){e.printStackTrace();}}, "龙珠" + i + "号").start();}}
每次执行 cyclicBarrier.await()一次障碍数会加一,当其达到对象CyclicBarrier中的NUMBER次数时将自动唤醒主线程
9.4 信号灯 Semaphore
Semaphore的构造方法中传入的第一个参数是最大信号量(可以看成最大线程池),每个信号量初始化为一个最多只能分发一个许可证。使用 acquire 方 法获得许可证,release 方法释放许可
场景: 抢车位, 6 部汽车 3 个停车位
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;public class SemaphoreDemo {/*** 抢车位, 10 部汽车 1 个停车位* @param args*/public static void main(String[] args) throws Exception {//定义 3 个停车位Semaphore semaphore = new Semaphore(3);//模拟 6 辆汽车停车for (int i = 1; i <= 6; i++) {Thread.sleep(100);//停车new Thread(() -> {try {semaphore.acquire();System.out.println(Thread.currentThread().getName() + "找车位 ing");TimeUnit.SECONDS.sleep(new Random().nextInt(5));System.out.println("----" + Thread.currentThread().getName() + "溜了溜了");} catch (Exception e) {e.printStackTrace();} finally {semaphore.release();}}, "汽车" + i).start();}}
}
执行效果
总结:
- CountDownLatch 数目明确,等量。
- CyclicBarrier 定量有富余,等积累到才触发。
- Semaphore 定量稀少,需要抢占。
- 应用领域不同,JUC三大辅助类为了解决线程资源争夺,线程池是为了解决线程开销
JUC并发编程之Callable接口、JUC三大辅助类相关推荐
- JUC并发编程之Java线程(二)
二.Java线程 2.1 创建和运行线程 方法一:Thread创建线程方式: 继承Thread类 匿名内部类方式 public class CreateThread01 {public static ...
- Java 并发编程之 Callable 和 Future
ExecutorService 执行完Callable 任务后,返回 Future 对象,Future 对象表示一个任务的生命周期,包含任务的状态和任务的结果对象. Future的get方法可以获得 ...
- JUC 高并发编程之JUC三大辅助类
JUC 高并发编程之JUC三大辅助类 JUC 中提供了三种常用的辅助类,通过这些辅助类可以很好的解决线程数量过 多时 Lock 锁的频繁操作.这三种辅助类为: CountDownLatch: 减少计数 ...
- cyclicbarrier java_Java并发编程之CyclicBarrier和线程池的使用
原标题:Java并发编程之CyclicBarrier和线程池的使用 下面我们来讲述一下线程池和CyclicBarrier的使用和对比. 一.场景描述 有四个游戏玩爱好者玩游戏,游戏中有三个关卡,每一个 ...
- java线程安全的set_Java并发编程之set集合的线程安全类你知道吗
Java并发编程之-set集合的线程安全类 Java中set集合怎么保证线程安全,这种方式你知道吗? 在Java中set集合是 本篇是<凯哥(凯哥并发编程学习>系列之<并发集合系列& ...
- java 时间戳_Java并发编程之CAS三CAS的缺点 及解决办法
Java并发编程之CAS第三篇-CAS的缺点 通过前两篇的文章介绍,我们知道了CAS是什么以及查看源码了解CAS原理.那么在多线程并发环境中,的缺点是什么呢?这篇文章我们就来讨论讨论 本篇是<凯 ...
- Java并发编程之CAS第三篇-CAS的缺点
Java并发编程之CAS第三篇-CAS的缺点 通过前两篇的文章介绍,我们知道了CAS是什么以及查看源码了解CAS原理.那么在多线程并发环境中,的缺点是什么呢?这篇文章我们就来讨论讨论 本篇是<凯 ...
- zbb20180929 thread java并发编程之Condition
java并发编程之Condition 引言 在java中,对于任意一个java对象,它都拥有一组定义在java.lang.Object上监视器方法,包括wait(),wait(long timeout ...
- python电路模型编程_14、python开发之路-并发编程之I/O模型
十四.并发编程之I/O模型 http://www.cnblogs.com/linhaifeng/articles/7454717.html 1.模型介绍 1.1 IO种类 (1)* blocking ...
最新文章
- 自学Python从哪学方面入手?
- 10年后的计算机会是怎样的?
- ExtJS 等待两个/多个store加载完再执行操作
- Global.asax或IHttpModule实现屏蔽ip和图片防盗链
- 【Java类加载机制】深入加载器
- Go Web编程--应用数据库
- 算法 查找子节点_掌握着十大编程算法助你走上高手之路
- java字符串元素置于最前_java_java编程常用技术(推荐),一:将String字符串放在最前面 - phpStudy...
- vb全局热键的写法(占很少的资源)
- MFC 线程创建方式
- 大合集!2019-2020年目标跟踪资源全汇总(论文、模型代码、优秀实验室)
- 如何交叉编译fio并移植到ARM、IOT上
- 【nn.Parameter】Pytorch特征融合自适应权重设置(可学习权重使用)
- 清华计算机录取通知书,清华送出第一批录取通知书,这些被刷屏的学霸,有怎样的成长密码...
- 鼠标左键双击图标出现属性窗口的问题
- [机缘参悟-52]:交浅言深要因人而异
- 在OTFS学习中的一些总结
- ESP8266模块三种低功耗睡眠模式
- (附源码)电影选座订票app 毕业设计 011439
- nohup python