Java中的多线程(下)
目录
一、juc下的Lock
1.接口Lock
2.接口实现类——ReentrantLock类
2.1基本格式:
2.2其他方法的演示与区别
2.3 synchronized VS ReentrantLock
二、volatile机制
三、单例模式(懒汉、饿汉)
1.饿汉模式
2.懒汉模式
四、wait() 和 notify()
五、阻塞队列
1.Who?
2.典型应用——生产者消费者模型
(1)什么是生产者-消费者模型
(2)引入阻塞队列的作用:
3.自己实现一个基于数组的阻塞队列
4.生产者-消费者模型的应用
五、定时器
1.定时器的使用
2.定时器的内部原理实现
【面试题】sleep和wait的区别:
六、线程池
1.存在的意义及初识
2.实现一个线程池(Runnable command)——实现Executor接口
一、juc下的Lock
sycchronized锁是在JVM内部实现的,是一种非常早期就存在的锁,而在我们的jdk标准库中,也定义实现了类似的锁机制,以类、对象的形式给我们使用,不再是简单的语言层面
1.接口Lock
(1)juc包指的是 java.util.concurrent.*,现代写并发编程都尽量使用juc包下提供的工具
(2)Lock
实现提供比使用synchronized
方法和语句可以获得的更广泛的锁定操作。 它们允许更灵活的结构化,可能具有完全不同的属性,并且可以支持多个相关联的对象Condition
(3)juc下的锁,定义了接口Lock
Lock接口下的方法定义如下图:
(1)lock()——普通的加锁操作,相当于synchronized加锁
(2)lockInterruptibly()——允许被打断的加锁,就是说,使用这种加锁操作,是允许被interrupted的,如果被打断,我就会停止我的加锁操作,而我们之前的加锁方式即使收到了interrupted信号,也是停不下来的
(3)tryLock()——是对加锁操作的结果处理,如果我没有加到锁,就返回false(可以在没加到锁的时间里先去做些别的事)
(4)tryLock(long time,TimeUnit unit)——在一定时间内如果都没加到锁,就返回false
(5)unLock()——解锁操作
Lock
实现提供了使用synchronized
方法和语句的附加功能,通过提供非阻塞尝试来获取锁( tryLock()
),尝试获取可被中断的锁( lockInterruptibly()
) ,以及尝试获取可以超时( tryLock(long, TimeUnit)
)
相较于synchronized锁,加锁策略更加的灵活
2.接口实现类——ReentrantLock类
目前的实现类有三个
这里我们主要学习ReentrantLock类(re-entrant——可重入),可重入的互斥锁
2.1基本格式:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/**juc下lock的使用* @author sunny* @date 2022/05/02 08:52**/
public class Creat {public static void main(String[] args) {Lock lock = new ReentrantLock();
// 加锁lock.lock();try {
// 在try语句块中放临界代码} finally {
// 在finally中解锁,确保任何情况下都能解锁lock.unlock();}}
}
如之前我们写过的加1000次1,再减1000次1的例子,使用juc下的ReentrantLock写,如下:(lock()操作跟synchronized锁一样,只是写法不一样罢了)
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/**juc下的锁* @author sunny* @date 2022/05/02 10:11**/
public class Main66 {static int r = 0;// 定义加减的次数// COUNT 越大,出错的概率越大;COUNT 越小,出错的概率越小static final int COUNT = 1_0000_0000;// 定义两个线程,分别对 r 进行 加法 + 减法操作// r++ 和 r-- 互斥static class Add extends Thread {private Lock o;Add(Lock o) {this.o = o;}@Overridepublic void run() {
// 加锁锁o.lock();try{for (int i = 0; i < COUNT; i++) {r++; // r++ 是原子的}}finally {o.unlock();}}}static class Sub extends Thread {private Lock o;Sub(Lock o) {this.o = o;}@Overridepublic void run() {o.lock();try {for (int i = 0; i < COUNT; i++) {r--; // r-- 是原子的的}}finally {o.unlock();}}}public static void main(String[] args) throws InterruptedException {
// 利用构造传入同一把锁Lock o = new ReentrantLock();Main6.Add add = new Main6.Add(o);add.start();Main6.Sub sub = new Main6.Sub(o);sub.start();add.join();sub.join();System.out.println(r);}}
2.2其他方法的演示与区别
(1)主线程lock()方法忘记解锁而导致子线程永远也拿不到锁
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/**死锁* @author sunny* @date 2022/05/02 10:21**/
public class DeadlyLock {private static final Lock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {
// 主线程加锁而未解锁lock.lock();
// 子线程则是永远也得不到锁的MyThread t = new MyThread();t.start();t.join();}static class MyThread extends Thread{@Overridepublic void run() {lock.lock();System.out.println("进入子线程");}}
}
(2)lock()方法即使使用interrupted中断信号,也是停不下来的
(3)而使用lockInterruptibly方法则允许中断
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** lockInterruptibly方法则允许中断** @author sunny* @date 2022/05/02 10:36**/
public class LockInterruptibly {private static final Lock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {
// 主线程加锁而未解锁lock.lock();MyThread t = new MyThread();t.start();TimeUnit.SECONDS.sleep(2);
// 中断子线程t.interrupt();}static class MyThread extends Thread {@Overridepublic void run() {try {lock.lockInterruptibly();System.out.println("进入子线程");} catch (InterruptedException e) {System.out.println("收到停止信号,停下来了");}}}
}
结果看到:程序是运行结束了的
(4)tryLock()操作
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/**tryLock操作* @author sunny* @date 2022/05/02 10:43**/
public class TryLock {private static final Lock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {
// 主线程加锁而未解锁lock.lock();MyThread t = new MyThread();t.start();TimeUnit.SECONDS.sleep(2);
// 中断子线程t.interrupt();}static class MyThread extends Thread {@Overridepublic void run() {boolean b = lock.tryLock();if (b == true){System.out.println("加锁成功,进入子线程");}else{System.out.println("加锁失败");
// 可以继续执行我要做的别的十二System.out.println("其他代码执行");}}}
}
(5)带时间的tryLock
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/**带时间的tryLock* @author sunny* @date 2022/05/02 10:48**/
public class TryLockWithTime {private static final Lock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {
// 主线程加锁而未解锁lock.lock();MyThread t = new MyThread();t.start();TimeUnit.SECONDS.sleep(2);
// 中断子线程t.interrupt();}static class MyThread extends Thread {@Overridepublic void run() {boolean b = false;try {b = lock.tryLock(5, TimeUnit.SECONDS);if (b == true) {System.out.println("加锁成功,进入子线程");} else {System.out.println("加锁失败");
// 可以继续执行我要做的别的十二System.out.println("其他代码执行");}} catch (InterruptedException e) {System.out.println("俺被打断了呀");}}}
}
结果:
ps:修改一下代码:
如果我把主线程的锁解锁,同时休眠时间2秒<5秒,所以会加锁成功
如果我把主线程的锁解锁,同时休眠时间修改为10秒,10>5,所以会加锁失败
2.3 synchronized VS ReentrantLock
Java中的多线程(下)相关推荐
- java.text.SimpleDateFormat多线程下的问题
1. 今天在做性能压测的时候发现java.text.SimpleDateFormat多线程下的错误 2. 先贴出两段错误大家看一下: Exception in thread "pool-1- ...
- java中的多线程使用方式
文章目录 1 场景 2 直接创建线程 2.1 Thread创建线程 2.2 Runnable创建线程 2.3 Callable创建线程 3 自定义线程池 3.1 关于线程池 3.1 工具类创建 3.2 ...
- 草根方式学习java中的多线程
草根方式学习java中的多线程 下面有具体的代码和截图 源码点这里 多线程即在同一时间,可以做多件事情(说白了,就是齐头并进) 单线程就是按部就班 创建多线程有2种方式,分别是继承线程Thread类, ...
- java中实现多线程的三种方式
java中实现多线程的三种方式 1.实现多线程的方法: 在java中实现多线程的两途径:继承Thread类,实现Runable接口(Callable) 2.继承Thread类实现多线程: 继承类T ...
- Java中的多线程基本介绍
在 Java 中,多线程是指同时执行两个或多个线程以最大限度地利用 CPU 的过程. Java 中的线程是一个轻量级进程,只需要较少的资源即可创建和共享进程资源. 多线程和多进程用于 Java 中的多 ...
- Java基础——深入理解Java中的多线程(超级详细,值得你看)
Java中的多线程 进程(process)是程序的一次执行过程,或是正在运行的有一个程序,或是正在运行的一个程序.是一个动态的过程:有它自身的产生.存在和消亡的过程.--生命周期. 线程(thread ...
- JAVA中实现多线程
一,JAVA中实现多线程(一) 1,在Java中负责线程的这个功能的是Java.lang.Thread 这个类 2,可以通过创建 Thread 的实例来创建新的线程. 3,每个线程都是通过某个特定Th ...
- Java中控制多线程顺序执行
Java中控制多线程顺序执行 一.概述 二.普通示例 三.控制示例 3.1.设置线程优先级 3.2.使用线程类的join() 3.2.1.在主线程join() 3.2.2.在子线程join() 3.3 ...
- Java中的多线程编程(超详细总结)
文章目录 Java中的多线程编程(超详细总结) 一.线程与多线程的概念 二.线程与进程之间的关系 三.一个线程的生命周期 四.多线程的目的和意义 五.线程的实现的方式 Java中的多线程编程(超详细总 ...
- JAVA中的多线程(一)
JAVA中的多线程(一) 进程:是一个正在执行中的程序 每一个进程执行都有一个执行的顺序,该顺序是一个执行路径,或者叫控制单元 线程:就是进程中的一个独立的控制单元 线程在控制着进程的执行 一个进程中 ...
最新文章
- Python,OpenCV中的图像修复——cv2.inpaint()
- 【Qt】解决在linux上使用Qt的媒体模块(Qt += multimedia)缺少模块multimedia的问题
- Nginx简介及使用Nginx实现负载均衡的原理【通俗易懂,言简意赅】
- 留言板asp mysql_ASP简单入门(制作一个简单的留言板 )
- python决策树 value_机器学习 | 算法笔记(四)- 决策树算法以及代码实现
- 想多赚点钱,一个最简单的办法,找到适合自身的坑
- 如何简单粗暴地上手 TensorFlow 2.0?
- python 设计模式之装饰器模式 Decorator Pattern
- 计算机网络连接图标 红叉,Win10网络图标显示红叉叉 检测不到网卡驱动解决方案...
- 城通网盘,千军万马,千脑网盘,119g网盘哪个适合做网赚?
- android设置wifi蓝牙共享文件,无需互联网或蓝牙即可通过WiFi通过android共享文件...
- Google Earth Engine(GEE)农作物种植结构提取
- mysql中使用CONCAT()函数,TRUNCATE()函数将小数转换成百分比
- OneFlow 如何做静态图的算子对齐任务
- 星期一到星期日的英文
- WebView监听网页加载成功与失败
- 无垠PE组合工具箱纯净无广告的PE启动盘
- AMD HD7850 4G显卡刷Bios验真伪(二)
- python西游之路
- 精准营销,我们这样做
热门文章
- 服务器千兆网络显示10,win10系统如何查看网卡是千兆还是百兆
- Research report about the development of photoelectric imaging guidance technology and its applicati
- Markdown KaTex 正负号±
- WordPress 确保您的网站安全
- 银行办理CSS系统,简单的银行储蓄系统.doc
- VCSA6.7的磁盘扩容与备份、还原
- 每当在测试之路迷茫的时候来看看这篇文章
- 弄清Flink1.8的远程过程调用(RPC)
- 层次分析法及matlab代码
- JS设计模式初探——单例模式