Java多线程之wait、notify/notifyAll 详解,用wait 和notifyAll 以及synchronized实现阻塞队列,多线程拓展之ReentrantLock与Condition
前言:这几天看了很多关于多线程的知识,分享一波。(但是目前接触的项目还未用到过,最多用过线程池,想看线程池 请看我之前的博客)
关于基本的理论等 参考如下:
https://www.cnblogs.com/LipeiNet/p/6475851.html
https://www.cnblogs.com/moongeek/p/7631447.html
一:synchronized
synchronized中文解释是同步,那么什么是同步呢,解释就是程序中用于控制不同线程间操作发生相对顺序的机制,通俗来讲就是2点,第一要有多线程,第二当多个线程同时竞争某个资源的时候会有先后顺序。在java中有三种写synchronized的方式
- 第一种:
- 写在普通方法的前面,这种表示对实例对象加锁。
- 第二种:
- 写在静态方法前面,这种表示对类对象加锁
- 第三种:
- 写在代码块中,锁是Synchonized括号里配置的对象(可能是实例对象,也可能是类对象)
总体说来就2种,一种就是锁实例对象,一种锁类对象。
锁实例对象就是当多个线程同时操作这个实例对象的时候必须先获取锁,如果无法获取锁,则必须处于等待状态,而和锁类对象区别是,当多个线程同时操作的时候,任何以这个类对象实例化的对象都要获取锁才能操作
二:wait、notify已经notifyAll
wait、notify、notifyAll是Object对象的属性,并不属于线程。我们先解释这三个的一个很重要的概念
wait:使持有该对象的线程把该对象的控制权交出去,然后处于等待状态(这句话很重要,也就是说当调用wait的时候会释放锁并处于等待的状态)
notify:通知某个正在等待这个对象的控制权的线程可以继续运行(这个就是获取锁,使自己的程序开始执行,最后通过notify同样去释放锁,并唤醒正在等待的线程)
notifyAll:会通知所有等待这个对象控制权的线程继续运行(和上面一样,只不过是唤醒所有等待的线程继续执行)
三:这里插入我写出的阻塞队列代码
import java.util.ArrayList;
import java.util.List; public class BlockQueue { private List<String> list=new ArrayList<>();
private int listSize;
private Object lock=new Object(); //通过构造初始化list 大小
public BlockQueue(int size){
this.listSize=size;
System.out.println(Thread.currentThread().getName()+"初始化 完成 list 大小为:"+listSize);
}
public void put(String name){
synchronized (lock){
if(list.size()==listSize){
//队列已经满了
System.out.println(Thread.currentThread().getName()+":当前队列已经满了 需要等待...");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} // try {
// Thread.sleep(500);
// } catch (InterruptedException e) {
// e.printStackTrace();
// } list.add(name);
System.out.println(Thread.currentThread().getName()+": put 放入队列中的元素 "+name);
//唤醒其他所有 队列存或者取数据
lock.notifyAll(); }
} public String get(){
synchronized (lock){
if(list.size()==0){
//说明当前队列已经空了 需要等待
System.out.println(Thread.currentThread().getName()+":当前队列已空,需要等待放入元素..."); try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
} } // try {
// Thread.sleep(500);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
String name= list.get(0);
list.remove(0);
//唤醒其他所有 队列存或者取数据
lock.notifyAll();
System.out.println(Thread.currentThread().getName()+": 获取到队列数据 "+name);
return name;
}
} public static void main(String[] args) { BlockQueue queue=new BlockQueue(3); new Thread(() -> { queue.put("name1");
queue.put("name2");
queue.put("name3");
queue.put("name4");
queue.put("name5");
queue.put("name6");
queue.put("name7"); },"T1").start(); new Thread(() -> {
System.out.println(queue.get());
System.out.println(queue.get());
System.out.println(queue.get()); },"T2").start();
} }
这里可以查看更多知识点:
ReenTrantLock可重入锁(和synchronized的区别)总结
四:notifyAll唤醒所有阻塞线程。试想,我们是否能够显示的在代码中只唤醒“对方”处于阻塞状态的线程呢?
换句话说,在持有同一个锁的情况下,生产者只唤醒消费者,消费者只唤醒生产者,这样的需求是否能实现?
答案是可以的。使用Condition配合Lock,就能解决这样的需求了。
让我们来看看Condition,如何在多生产者消费者模型中实现交替唤醒功能。
拓展:入门AQS锁 - ReentrantLock与Condition
这里的拓展是出自简书:链接地址:https://www.jianshu.com/p/f207e85d0238
Java多线程之wait、notify/notifyAll 详解,用wait 和notifyAll 以及synchronized实现阻塞队列,多线程拓展之ReentrantLock与Condition的更多相关文章
- JAVA多线程之wait/notify
本文主要学习JAVA多线程中的 wait()方法 与 notify()/notifyAll()方法的用法. ①wait() 与 notify/notifyAll 方法必须在同步代码块中使用 ②wait ...
- iOS 多线程之NSOperation篇举例详解
这篇博客是接着总篇iOS GCD NSOperation NSThread等多线程各种举例详解写的一个支篇.总篇也包含了此文的链接.本文讲解的知识点有NSBlockOperationClick,队列, ...
- ios 多线程之NSThread篇举例详解
这篇博客是接着总篇iOS GCD NSOperation NSThread等多线程各种举例详解写的一个支篇.总篇也包含了此文的链接.本文讲解的知识点有NSThread的开始.取消.在当前线程执行任务. ...
- java 多线程之wait(),notify,notifyAll(),yield()
wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()的功能.因为都个对像都 ...
- Java多线程之wait(),notify(),notifyAll()
在多线程的情况下,因为同一进程的多个线程共享同一片存储空间,在带来方便的同一时候,也带来了訪问冲突这个严重的问题.Java语言提供了专门机制以解决这样的冲突,有效避免了同一个数据对象被多个线程同一时候 ...
- JAVA多线程之volatile 与 synchronized 的比较
一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空 ...
- java多线程之wait和notify协作,生产者和消费者
这篇直接贴代码了 package cn.javaBase.study_thread1; class Source { public static int num = 0; //假设这是馒头的数量 } ...
- java多线程之yield,join,wait,sleep的区别
Java多线程之yield,join,wait,sleep的区别 Java多线程中,经常会遇到yield,join,wait和sleep方法.容易混淆他们的功能及作用.自己仔细研究了下,他们主要的区别 ...
- Java多线程之ConcurrentSkipListMap深入分析(转)
Java多线程之ConcurrentSkipListMap深入分析 一.前言 concurrentHashMap与ConcurrentSkipListMap性能测试 在4线程1.6万数据的条件下, ...
随机推荐
- 28.实现 strStr() 函数
28.实现 strStr() 函数 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始).如果不存在, ...
- 目标检测算法(1)目标检测中的问题描述和R-CNN算法
目标检测(object detection)是计算机视觉中非常具有挑战性的一项工作,一方面它是其他很多后续视觉任务的基础,另一方面目标检测不仅需要预测区域,还要进行分类,因此问题更加复杂.最近的5年使 ...
- 谈一款MOBA类游戏《码神联盟》的服务端架构设计与实现(更新优化思路)
注:本文仅用于在博客园学习分享,还在随着项目不断更新和完善中,多有不足,暂谢绝各平台或个人的转载和推广,感谢支持. 一.前言 <码神联盟>是一款为技术人做的开源情怀游戏,每一种编程语言都是 ...
- 18年最有"钱"途的专业就是它(文末有福利)
根据社会调查机构麦可思发布的<2018年中国大学生就业报告>中得知,从就业率.薪资和就业满意度等多角度综合考量,信息安全专业为首推绿牌专业. 不管你是计算机相关专业的学生,还是已经工作的I ...
- Metasploit Framework(8)后渗透测试(一)
文章的格式也许不是很好看,也没有什么合理的顺序 完全是想到什么写一些什么,但各个方面都涵盖到了 能耐下心看的朋友欢迎一起学习,大牛和杠精们请绕道 使用场景: Kali机器IP:192.168.163. ...
- Kali学习笔记11:僵尸扫描案例
什么是僵尸扫描?本质也是端口扫描,不过是一种极其隐蔽的扫描方式 所以几乎不会被发现,不过也有着很大缺陷:扫描条件很高 首先需要有一台僵尸机,这里我找好一台win10僵尸机器,IP地址为:10.14.4 ...
- java项目引用证书文件(微信支付的p12文件)
1. 绝对路径: // windows: public static String PATH1 = "E:\\project27_app_wuyoujie\\apiclient_cert.p ...
- 机器学习(Machine Learning)算法总结-K临近算法
一.算法详解 1.什么是K临近算法 Cover 和 Hart在1968年提出了最初的临近算法 属于分类(classification)算法 邻近算法,或者说K最近邻(kNN,k-NearestNeig ...
- c++多继承多态
C++多继承多态的实现 如果一个类中存在虚函数,在声明类的对象时,编译器就会给该对象生成一个虚函数指针,该虚函数指针指向该类对应的虚函数表. 多态的实现是因为使用了一种动态绑定的机制,在编译期间不确定 ...
- [原创]K8 Jboss jmx-console getshell exploit
[原创]K8 Jboss jmx-console getshell exploit https://www.cnblogs.com/k8gege/p/10645858.html 0x00 前言 今天内 ...