前言:这几天看了很多关于多线程的知识,分享一波。(但是目前接触的项目还未用到过,最多用过线程池,想看线程池 请看我之前的博客)

关于基本的理论等 参考如下:

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的更多相关文章

  1. JAVA多线程之wait/notify

    本文主要学习JAVA多线程中的 wait()方法 与 notify()/notifyAll()方法的用法. ①wait() 与 notify/notifyAll 方法必须在同步代码块中使用 ②wait ...

  2. iOS 多线程之NSOperation篇举例详解

    这篇博客是接着总篇iOS GCD NSOperation NSThread等多线程各种举例详解写的一个支篇.总篇也包含了此文的链接.本文讲解的知识点有NSBlockOperationClick,队列, ...

  3. ios 多线程之NSThread篇举例详解

    这篇博客是接着总篇iOS GCD NSOperation NSThread等多线程各种举例详解写的一个支篇.总篇也包含了此文的链接.本文讲解的知识点有NSThread的开始.取消.在当前线程执行任务. ...

  4. java 多线程之wait(),notify,notifyAll(),yield()

    wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()的功能.因为都个对像都 ...

  5. Java多线程之wait(),notify(),notifyAll()

    在多线程的情况下,因为同一进程的多个线程共享同一片存储空间,在带来方便的同一时候,也带来了訪问冲突这个严重的问题.Java语言提供了专门机制以解决这样的冲突,有效避免了同一个数据对象被多个线程同一时候 ...

  6. JAVA多线程之volatile 与 synchronized 的比较

    一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空 ...

  7. java多线程之wait和notify协作,生产者和消费者

    这篇直接贴代码了 package cn.javaBase.study_thread1; class Source { public static int num = 0; //假设这是馒头的数量 } ...

  8. java多线程之yield,join,wait,sleep的区别

    Java多线程之yield,join,wait,sleep的区别 Java多线程中,经常会遇到yield,join,wait和sleep方法.容易混淆他们的功能及作用.自己仔细研究了下,他们主要的区别 ...

  9. Java多线程之ConcurrentSkipListMap深入分析(转)

    Java多线程之ConcurrentSkipListMap深入分析   一.前言 concurrentHashMap与ConcurrentSkipListMap性能测试 在4线程1.6万数据的条件下, ...

随机推荐

  1. day_10初级函数

    今天讲了函数初级 函数:完成特定功能的代码块,作为一个整体对其进行特定的命名,该名字就是代表函数 --现实中很多问题要通过一些工具进行处理 ,,可以将工具提前准备好并命名 通过名字就可以找到这个工具 ...

  2. [转]CSS clear both清除浮动

    DIV+CSS clear both清除产生浮动 我们知道有时使用了css float浮动会产生css浮动,这个时候就需要清理清除浮动,我们就用clear样式属性即可实现. 接下来我们来认识与学习cs ...

  3. html input file accept 上传文件类型限制格式 MIME 类型列表

    例: <input type="file" accept="application/vnd.openxmlformats-officedocument.spread ...

  4. Fiddler工具使用介绍一

    Fiddler基础知识 Fiddler是强大的抓包工具,它的原理是以web代理服务器的形式进行工作的,使用的代理地址是:127.0.0.1,端口默认为8888,我们也可以通过设置进行修改. 代理就是在 ...

  5. JSON Web Token(JWT)使用步骤说明

    在JSON Web Token(JWT)原理和用法介绍中,我们了解了JSON Web Token的原理和用法的基本介绍.本文我们着重讲一下其使用的步骤: 一.JWT基本使用 Gradle下依赖 : c ...

  6. Redis学习笔记之延时队列

    目录 一.业务场景 二.Redis延时队列 一.业务场景 所谓延时队列就是延时的消息队列,下面说一下一些业务场景比较好理解 1.1 实践场景 订单支付失败,每隔一段时间提醒用户 用户并发量的情况,可以 ...

  7. Xamarin.Android 解决打开软键盘导致底部菜单上移问题

    在界面布局中有EditText控件,该控件一旦获取焦点则打开软键盘,如果布局中有底部菜单,那么底部菜单可能会被软键盘顶在其上面,看如下效果: 解决方法:在活动绑定界面之前写上下段代码即可 Window ...

  8. while true 死循环判断端口按顺序启动应用

    需求:spring微服务应用启动较慢并且要求一个应用启完才能启第二个应用. 思路:加了个while true 死循环判断端口启动了才启下一个应用. 执行方式:/appupgrade/spring_cl ...

  9. 一些不常用但又很有用的css小tips

    1.box-sizing:border-box box-sizing有三个属性:content-box(默认值) || border-box || inhreit.第一个自然不用说,比如我们设置一个d ...

  10. poj1001

    #include <iostream> #include<iomanip> #include<cstring> using namespace std; int s ...