首页 > 其他分享 >多线程五-线程通信之wait与notify

多线程五-线程通信之wait与notify

时间:2024-09-15 22:12:48浏览次数:8  
标签:bags 生产者 Queue 线程 notify import 多线程 public

wait与notify用于syncronized的线程间通信的一种,wait用来阻塞线程并释放锁,notify用来唤醒线程。他们与condition作用基本一致,但是由于syncronized为jdk实现,阅读源码有难度,所以通过了解其原理,用来帮助我们后续理解condition的源码。
可以通过下面一张图来理解:
syncronized.png
下面通过一个简单的生产者与消费者的例子来体会一下这两个API的用法
生产者代码:

package com.caozz.demo5.concurrent;

import java.util.Queue;

public class Producer implements Runnable{

    private Queue<String> bags;

    private int maxSize;

    public Producer(Queue<String> bags, int maxSize) {
        this.bags = bags;
        this.maxSize = maxSize;
    }

    @Override
    public void run(){
        int i = 0;
        while (true) {
            i++;
            synchronized (bags) {
                if (bags.size() >= maxSize) {
                    System.out.println("bags 满了");
                    try {
                        bags.wait();//满了则阻塞当前线程并释放
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("生产者生产: bag" + i);
                bags.add("bag" + i);
                bags.notify();//表示已经生产数据了,消费者可以消费了(消费者不一定能抢到锁)
            }
        }
    }

}

消费者代码:

package com.caozz.demo5.concurrent;

import java.util.Queue;

public class Consumer  implements Runnable{
    private Queue<String> bags;


    public Consumer(Queue<String> bags){
        this.bags = bags;
    }

    @Override
    public void run() {
        while (true) {
            //与生产者肯定是同一个对象,否则不是同一把锁就无法实现线程间通信了
            synchronized (bags) {
                if (bags.isEmpty()) {
                    System.out.println("bags 为空");
                    try {
                        bags.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
                String bag = bags.remove();
                System.out.println("消费者消费:" + bag);
                //如果生产者满了被阻塞,此时消费了所以必然可以继续生产
                //这里只是唤醒线程,但是生产者并不能马上执行,因为需要等到同步代码块执行完成,即monitorexit指令执行完成
                bags.notify();
            }
        }
    }
}

测试:

package com.caozz.demo5.controller;

import com.caozz.demo5.concurrent.Consumer;
import com.caozz.demo5.concurrent.Producer;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test {
    public static void main(String[] args) throws InterruptedException {
//        Lock lock = new ReentrantLock(true);
//        lock.lock();
//        lock.unlock();
        Queue<String> bags = new LinkedList<>();
        int maxSize = 500;
        Producer producer = new Producer(bags, maxSize);
        Consumer consumer = new Consumer(bags);

        new Thread(producer).start();
        Thread.sleep(1);
        new Thread(consumer).start();
    }
}

部分执行结果:省略号省略得内容连续

消费者消费:bag183545
消费者消费:bag183546
消费者消费:bag183547
生产者生产: bag183572
生产者生产: bag183573
...
生产者生产: bag183580
消费者消费:bag183548
...
消费者消费:bag183580
bags 为空
生产者生产: bag183581
生产者生产: bag183582
消费者消费:bag183581
消费者消费:bag183582
bags 为空
生产者生产: bag183583
...
生产者生产: bag183591
消费者消费:bag183583
消费者消费:bag183584
欢迎大家留言,以便于后面的人更快解决问题!另外亦欢迎大家可以关注我的微信公众号,方便利用零碎时间互相交流。共勉!

标签:bags,生产者,Queue,线程,notify,import,多线程,public
From: https://www.cnblogs.com/caozz/p/18415759/thread-sychronized-wait-notify

相关文章

  • [Java并发]守护线程
    守护线程和普通线程的最大区别是守护线程会在主线程结束后退出,但是普通线程在主线程结束后不会退出。普通线程的执行importjava.sql.Time;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;publicclassMain{publicstaticvoid......
  • Python 课程8-多线程编程和多进程编程
    前言        在现代编程中,处理并发任务是提高程序性能的关键之一。Python提供了多线程(threading)和多进程(multiprocessing)两种方式来实现并发编程。多线程适用于I/O密集型任务,而多进程则更适合CPU密集型任务。通过这两种技术,你可以高效地处理大规模数据、加速......
  • 浅谈线程的创建方式
    引言在网上查询这个问题,大多回答是线程的创建方式有四种。继承Thread类实现Runnable接口实现Callable接口使用线程池但是这种说法是错误的,或者说是不正确的不严谨的。我的想法实际上,在Java中创建线程的方式只有一种,就是使用newThread()只有这样才能创建一个线......
  • 多线程篇(面试题)(持续更新迭代)
    目录文档说明一、线程的基础知识1.线程和进程的区别?2.并行和并发有什么区别?3.创建线程的四种方式4.runnable和callable有什么区别5.线程的run()和start()有什么区别?6.线程包括哪些状态,状态之间是如何变化的7.新建T1、T2、T3三个线程,如何保证它们按顺序......
  • C++实现线程池
    目录一.什么是线程池二.为什么要用线程池三.如何实现线程池这篇文章简单讨论下线程池。一.什么是线程池线程池简单来时就是维护了一组线程的池子,这组线程执行一些相似任务。是一种线程的使用方式。二.为什么要用线程池有的时候系统需要处理大量相似任务,频繁创建销......
  • Java HashMap详解:源码分析、hash 原理、扩容机制、加载因子、线程不安全
    这篇文章将会详细透彻地讲清楚Java的HashMap,包括hash方法的原理、HashMap的扩容机制、HashMap的加载因子为什么是0.75而不是0.6、0.8,以及HashMap为什么是线程不安全的,基本上HashMap的常见面试题,都会在这一篇文章里讲明白。HashMap是Java中常用的数据结构之一......
  • modbus调试助手/mqtt调试工具/超轻巧物联网组件/多线程实时采集/各种协议支持
    一、前言说明搞物联网开发很多年,用的最多的当属modbus协议,一个稳定好用的物联网组件是物联网平台持续运行多年的基石,所以这个物联网组件从一开始就定位于自研,为了满足各种场景的需求,当然最重要的一点就是大大提升了自己对该协议的深度理解和应用,尤其是面对各种场景需求,逐步调整迭......
  • springboot动态线程池
    1、配置文件新增每个线程池的基本参数配置thread-pool.user-thread.corePoolSize=1thread-pool.user-thread.maxPoolSize=1thread-pool.user-thread.keepAliveSeconds=120thread-pool.user-thread.queueCapacity=1thread-pool.school-thread.corePoolSize=2thread-pool.sch......
  • C#笔记13 线程同步概念及其实现,详解lock,Monitor,Mutex代码用法
    同步的概念在我们学会在C#中使用线程之后,我们拥有了把一个程序中的不同代码段在不同线程中运行的能力,可以说此时我们已经能够做到让他们分别执行,异步执行。对于我们的桌面端程序,使用多线程可以让我们在后台进行操作的时候保持用户界面的响应。对于服务器应用程序,多线程可以......
  • 《深入理解 Java 中的多线程基础(篇一)》
    多线程基础概述现代操作系统(Windows,macOS,Linux)都可以执行多任务。多任务就是同时运行多个任务。例如:播放音乐的同时,浏览器可以进行文件下载,同时可以进行QQ消息的收发。CPU执行代码都是一条一条顺序执行的,但是,即使是单核CPU,也可以同时运行多个任务。因为操作系统执行多任......