5. CountDownLatch 闭锁

Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器的性能。

CountDownLatch 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

闭锁可以延迟线程的进度直到其到达终止状态,闭锁可以用来确保某些活动直到其他活动都完成才继续执行:

  • 确保某个计算在其需要的所有资源都被初始化之后才继续执行;
  • 确保某个服务在其依赖的所有其他服务都已经启动之后才启动;
  • 等待直到某个操作所有参与者都准备就绪再继续执行。

如下:要求在创建的5个线程都执行完毕之后,再调用线程main方法输出耗费时间,使用wait,notify和notifyAll方法也可实现,但JDK不推荐。这里使用CountDownLatch。

/*
* CountDownLatch :闭锁,在完成某些运算时,只有其他所有线程的运算全部完成,当前运算才继续执行
*/
public class TestCountDownLatch { public static void main(String[] args) {
//CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果你想等待N个点完成,这里就传入N。
final CountDownLatch latch = new CountDownLatch(5);
LatchDemo ld = new LatchDemo(latch); long start = System.currentTimeMillis(); for (int i = 0; i < 5; i++) {
new Thread(ld).start();
} try {
//阻塞当前线程,直到N变成零。
latch.await();
} catch (InterruptedException e) {
} long end = System.currentTimeMillis(); System.out.println("耗费时间为:" + (end - start));
} } class LatchDemo implements Runnable { private CountDownLatch latch;
public LatchDemo(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}
} finally { //计数器减一
latch.countDown();
}
}
}

结果:

6. 创建执行线程的方式三:实现 Callable 接口

Thread类和Runnable接口都不允许声明检查型异常,也不能定义返回值。Thread类和Runnable接口都不允许声明检查型异常,也不能定义返回值。

不能声明抛出检查型异常这个问题比较麻烦。public void run()方法契约意味着你必须捕获并处理检查型异常。即使你小心地保存了异常信息(在捕获异常时)以便稍后检查,但也不能保证这个类(Runnable对象)的所有使用者都读取异常信息。你也可以修改Runnable实现的getter,让它们都能抛出任务执行中的异常。但这种方法除了繁琐也不是十分安全可靠,你不能强迫使用者调用这些方法,程序员很可能会调用join()方法等待线程结束然后就不管了。

Java 5.0 在 java.util.concurrent 提供了一个新的创建执行线程的方式:Callable 接口。Callable接口定义了方法public T call() throws Exception。我们可以在Callable实现中声明强类型的返回值,甚至是抛出异常。

Future是Java 1.5中引入的接口,当你提交一个Callable对象给线程池时,将得到一个Future对象,并且它和你传入的Callable有相同的结果类型声明。这个对象取代了Java 1.5之前直接操作具体Thread实例的做法。过去你不得不用Thread.join()或者Thread.join(long millis)等待任务完成。

Callable 需要依赖FutureTask(Future子类RunnableFuture的实现类) ,FutureTask 也可以用作闭锁。

/*
* 一、创建执行线程的方式三:实现 Callable 接口。 相较于实现 Runnable 接口的方式,方法可以有返回值,并且可以抛出异常。
*
* 二、执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。 FutureTask 是 Future 接口的实现类
*/
public class TestCallable { public static void main(String[] args) {
ThreadDemo1 td = new ThreadDemo1(); //1.执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。
FutureTask<Integer> result = new FutureTask<>(td); new Thread(result).start(); //2.接收线程运算后的结果
try {
Integer sum = result.get(); //FutureTask 可用于 闭锁
System.out.println(sum);
System.out.println("------------------------------------");
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
} class ThreadDemo1 implements Callable<Integer>{ @Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i <= 100000; i++) {
sum += i;
}
return sum;
}
} /*class ThreadDemo implements Runnable{
@Override
public void run() {
}
}*/

7. 同步锁 Lock

在 Java 5.0 之前,协调共享对象的访问时可以使用的机制只有 synchronized 和 volatile 。Java 5.0 后增加了一些新的机制,但并不是一种替代内置锁的方法,而是当内置锁不适用时,作为一种可选择的高级功能。

ReentrantLock 实现了 Lock 接口,并提供了与synchronized 相同的互斥性和内存可见性。但相较于synchronized 提供了更高的处理锁的灵活性。

/*
* 用于解决多线程安全问题的方式:
*
* synchronized:隐式锁
* 1. 同步代码块
*
* 2. 同步方法
*
* jdk 1.5 后:
* 3. 同步锁 Lock
* 注意:是一个显示锁,需要通过 lock() 方法上锁,必须通过 unlock() 方法进行释放锁
*/
public class TestLock {
public static void main(String[] args) {
Ticket ticket = new Ticket(); new Thread(ticket, "1号窗口").start();
new Thread(ticket, "2号窗口").start();
new Thread(ticket, "3号窗口").start();
}
} class Ticket implements Runnable{
private int tick = 100; private Lock lock = new ReentrantLock(); @Override
public void run() {
while(true){
lock.lock(); //上锁
try{
if(tick > 0){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + " 完成售票,余票为:" + --tick);
}
}finally{
lock.unlock(); //释放锁
}
}
}
}

(二)juc线程高级特性——CountDownLatch / Callable / Lock的更多相关文章

  1. (四)juc线程高级特性——线程池 / 线程调度 / ForkJoinPool

    13. 线程池 第四种获取线程的方法:线程池,一个 ExecutorService,它使用可能的几个池线程之一执行每个提交的任务,通常使用 Executors 工厂方法配置. 线程池可以解决两个不同问 ...

  2. (一)juc线程高级特性——volatile / CAS算法 / ConcurrentHashMap

    1. volatile 关键字与内存可见性 原文地址: https://www.cnblogs.com/zjfjava/category/979088.html 内存可见性(Memory Visibi ...

  3. Java多线程系列--“JUC线程池”06之 Callable和Future

    概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...

  4. 【Redis】二、Redis高级特性

    (三) Redis高级特性   前面我们介绍了Redis的五种基本的数据类型,灵活运用这五种数据类型是使用Redis的基础,除此之外,Redis还有一些特性,掌握这些特性能对Redis有进一步的了解, ...

  5. 7.JUC线程高级-生产消费问题&虚假唤醒

    描述 生产消费问题在java多线程的学习中是经常遇到的问题 ,多个线程共享通一个资源的时候会出现各种多线程中经常出现的各种问题. 实例说明 三个类:售货员Clerk,工厂Factory,消费者Cons ...

  6. MapReduce(二) MR的高级特性-序列化、排序、分区、合并

    一.序列化   (*) 核心接口:Writable接口.如果有一个类实现了Writable接口,就可以作为Map/Reduce的key和value.    举例: 读取员工数据,生成员工对象,直接存储 ...

  7. (二)python高级特性

    一.切片 >>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack'] 对这种经常取指定索引范围的操作,用循环十分繁琐,因此,Python ...

  8. Java - "JUC线程池" Callable与Future

    Java多线程系列--“JUC线程池”06之 Callable和Future Callable 和 Future 简介 Callable 和 Future 是比较有趣的一对组合.当我们需要获取线程的执 ...

  9. Zookeeper系列五:Master选举、ZK高级特性:基本模型

    一.Master选举 1. master选举原理: 有多个master,每次只能有一个master负责主要的工作,其他的master作为备份,同时对负责工作的master进行监听,一旦负责工作的mas ...

随机推荐

  1. BAT 删除隐藏文件

    删除文件 del命令参数说明/F   强制删除文件./S      从所有子目录删除指定文件./Q      安静模式.删除全局通配符时,不要求确认./A      根据属性选择要删除的文件. 删除指 ...

  2. Unitek的USB3.0 TF卡读卡器

    淘宝买了个Unitek的usb3.0读卡器, 用来换掉之前用了很久sks的sub2读卡器, 收到之后在Ubuntu下先测了一下, 发现识别出来的是usb2.1 lsusb -D /dev/bus/us ...

  3. RobotFrameWork环境搭建(基于HTTP协议的接口自动化)

    1. 前言 接着上一篇<RobotFramework框架系统课程介绍>,本篇主要介绍一下在基于RobotFramework框架开展接口自动化前,前期的环境如何搭建,正所谓”工欲善其事,必先 ...

  4. P2P贷款全攻略,贷前、贷中、贷后工作事项解析

    一.贷前调查事项 贷前调查是所有银行.小贷.P2P等等往出贷款部门的重中之重. 归根结底就是两条:让不对称信息最大限度对称.让软信息最大限度真实还原. 客户还不还款就是取决两大因素:还款能力.还款意愿 ...

  5. Linux内核同步

    Linux内核剖析 之 内核同步 主要内容 1.内核请求何时以交错(interleave)的方式执行以及交错程度如何. 2.内核所实现的基本同步机制. 3.通常情况下如何使用内核提供的同步机制. 内核 ...

  6. Android 异常 android.os.NetworkOnMainThreadException

    近期在实现一个Android下的数据採集的SDK,收集用户使用数据使用HTTP发送到云平台.进行数据分析.但在发送数据时报例如以下错误: Caused by: android.os.NetworkOn ...

  7. Atitit 关于处理环保行动联盟和动物解放阵线游击队的任命书 委任状

    Atitit 关于处理环保行动联盟和动物解放阵线游击队的任命书 委任状 Uke 集团文化部部长兼emir 大酋长圣旨到!! In god we trust ,Emir Decree大酋长圣旨:: En ...

  8. webview调起浏览器

    调起浏览器 url = "intent://" + url +"#Intent;scheme=http;action=android.intent.action.VIEW ...

  9. Session 在分布式系统中实现方式

    ##server独立Session 例如以下图所看到的: server独立Session要求用户的每次请求都必须在同一台应用server上面操作,这就要求负载均衡server每次都能把用户的请求发送到 ...

  10. matplotlib绘图不显示问题解决plt.show()

    最近在看<Python数据分析>这本书,而自己写代码一直用的是Pycharm,在练习的时候就碰到了plot()绘图不能显示出来的问题.网上翻了一下找到知乎上一篇回答,试了一下好像不行,而且 ...