目录

一、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中的多线程(下)相关推荐

  1. java.text.SimpleDateFormat多线程下的问题

    1. 今天在做性能压测的时候发现java.text.SimpleDateFormat多线程下的错误 2. 先贴出两段错误大家看一下: Exception in thread "pool-1- ...

  2. java中的多线程使用方式

    文章目录 1 场景 2 直接创建线程 2.1 Thread创建线程 2.2 Runnable创建线程 2.3 Callable创建线程 3 自定义线程池 3.1 关于线程池 3.1 工具类创建 3.2 ...

  3. 草根方式学习java中的多线程

    草根方式学习java中的多线程 下面有具体的代码和截图 源码点这里 多线程即在同一时间,可以做多件事情(说白了,就是齐头并进) 单线程就是按部就班 创建多线程有2种方式,分别是继承线程Thread类, ...

  4. java中实现多线程的三种方式

    java中实现多线程的三种方式 1.实现多线程的方法: 在java中实现多线程的两途径:继承Thread类,实现Runable接口(Callable) 2.继承Thread类实现多线程: ​ 继承类T ...

  5. Java中的多线程基本介绍

    在 Java 中,多线程是指同时执行两个或多个线程以最大限度地利用 CPU 的过程. Java 中的线程是一个轻量级进程,只需要较少的资源即可创建和共享进程资源. 多线程和多进程用于 Java 中的多 ...

  6. Java基础——深入理解Java中的多线程(超级详细,值得你看)

    Java中的多线程 进程(process)是程序的一次执行过程,或是正在运行的有一个程序,或是正在运行的一个程序.是一个动态的过程:有它自身的产生.存在和消亡的过程.--生命周期. 线程(thread ...

  7. JAVA中实现多线程

    一,JAVA中实现多线程(一) 1,在Java中负责线程的这个功能的是Java.lang.Thread 这个类 2,可以通过创建 Thread 的实例来创建新的线程. 3,每个线程都是通过某个特定Th ...

  8. Java中控制多线程顺序执行

    Java中控制多线程顺序执行 一.概述 二.普通示例 三.控制示例 3.1.设置线程优先级 3.2.使用线程类的join() 3.2.1.在主线程join() 3.2.2.在子线程join() 3.3 ...

  9. Java中的多线程编程(超详细总结)

    文章目录 Java中的多线程编程(超详细总结) 一.线程与多线程的概念 二.线程与进程之间的关系 三.一个线程的生命周期 四.多线程的目的和意义 五.线程的实现的方式 Java中的多线程编程(超详细总 ...

  10. JAVA中的多线程(一)

    JAVA中的多线程(一) 进程:是一个正在执行中的程序 每一个进程执行都有一个执行的顺序,该顺序是一个执行路径,或者叫控制单元 线程:就是进程中的一个独立的控制单元 线程在控制着进程的执行 一个进程中 ...

最新文章

  1. Python,OpenCV中的图像修复——cv2.inpaint()
  2. 【Qt】解决在linux上使用Qt的媒体模块(Qt += multimedia)缺少模块multimedia的问题
  3. Nginx简介及使用Nginx实现负载均衡的原理【通俗易懂,言简意赅】
  4. 留言板asp mysql_ASP简单入门(制作一个简单的留言板 )
  5. python决策树 value_机器学习 | 算法笔记(四)- 决策树算法以及代码实现
  6. 想多赚点钱,一个最简单的办法,找到适合自身的坑
  7. 如何简单粗暴地上手 TensorFlow 2.0?
  8. python 设计模式之装饰器模式 Decorator Pattern
  9. 计算机网络连接图标 红叉,Win10网络图标显示红叉叉 检测不到网卡驱动解决方案...
  10. 城通网盘,千军万马,千脑网盘,119g网盘哪个适合做网赚?
  11. android设置wifi蓝牙共享文件,无需互联网或蓝牙即可通过WiFi通过android共享文件...
  12. Google Earth Engine(GEE)农作物种植结构提取
  13. mysql中使用CONCAT()函数,TRUNCATE()函数将小数转换成百分比
  14. OneFlow 如何做静态图的算子对齐任务
  15. 星期一到星期日的英文
  16. WebView监听网页加载成功与失败
  17. 无垠PE组合工具箱纯净无广告的PE启动盘
  18. AMD HD7850 4G显卡刷Bios验真伪(二)
  19. python西游之路
  20. 精准营销,我们这样做

热门文章

  1. 服务器千兆网络显示10,win10系统如何查看网卡是千兆还是百兆
  2. Research report about the development of photoelectric imaging guidance technology and its applicati
  3. Markdown KaTex 正负号±
  4. WordPress 确保您的网站安全
  5. 银行办理CSS系统,简单的银行储蓄系统.doc
  6. VCSA6.7的磁盘扩容与备份、还原
  7. 每当在测试之路迷茫的时候来看看这篇文章
  8. 弄清Flink1.8的远程过程调用(RPC)
  9. 层次分析法及matlab代码
  10. JS设计模式初探——单例模式