8_4、Java基本语法之线程的通信
创始人
2024-03-25 16:13:48
0

一、问题的引入

        使用两个线程打印 1-100。线程1, 线程2交替打印?

二、解决问题涉及的方法

        涉及到的三个方法:

        1.wait():一旦执行此方法,那么调用此方法的线程就会进入阻塞状态,并释放同步监视器。            2.notify():一个线程执行此方法,会唤醒一个被wait的线程。如果有多个被wait的线程,那么唤醒优先级高的线程。

        3.notifyAll():一个线程执行此方法,会唤醒所有被wait的线程。

class Number implements Runnable{private int number = 1;private Object obj = new Object();@Overridepublic void run() {while(true){synchronized (obj) {obj.notify();if(number <=100){System.out.println(Thread.currentThread().getName() + ":" + number);number++;try {//使得调用wait()的线程进入阻塞状态obj.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}else{break;}}}}
}public class CommunicationTest {public static void main(String[] args) {Number num = new Number();Thread t1 = new Thread(num);Thread t2 = new Thread(num);t1.setName("线程1");t2.setName("线程2");t1.start();t2.start();}
}

运行结果:

关于三个方法的说明:

1.wait()、notify()、notifyAll()这三个方法必须写在同步代码块或者同步方法中

2.wait()、notify()、notifyAll()这三个方法的调用者必须与同步代码块或者同步方法的同步监视器一致。 否则会报错:IllegalMonitorStateException。

3.wait()、notify()、notifyAll()这三个方法定义在java.lang.Objct类中。

三、经典例题

        生产者/消费者问题:生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处 取走产品,店员一次只能持有固定数量的产品(比如:20),如果生产者试图 生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通 知生产者继续生产;如果店中没有产品了,店员会告诉消费者等一下,如 果店中有产品了再通知消费者来取走产品。

这里可能出现两个问题: ①生产者比消费者快时,消费者会漏掉一些数据没有取到。 ②消费者比生产者快时,消费者会取相同的数据。

解决思路:

是否有多个线程?有,生产者、消费者

是否由共享数据?有,店员(产品)

是否有线程安全问题?有

如何解决线程安全问题?三种方式

//店员
class Clerk{private int numCount = 0;//生产产品public synchronized void produceProduct() {if (numCount < 20) {numCount++;try {Thread.sleep(10);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(Thread.currentThread().getName() + "生产了第" + numCount +"个产品");notify();}else{try {wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}}//消费产品public synchronized void cusumerProduct() {if(numCount>0){System.out.println(Thread.currentThread().getName() + "消费了第" + numCount + "个产品");numCount--;try {Thread.sleep(20);} catch (InterruptedException e) {throw new RuntimeException(e);}notify();}else{try {wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
//生产者
class Productor extends Thread{private Clerk clerk;public Productor(Clerk clerk) {this.clerk = clerk;}@Overridepublic void run() {while (true) {clerk.produceProduct();}}
}//消费者
class Customer extends Thread{private Clerk clerk;public Customer(Clerk clerk) {this.clerk = clerk;}@Overridepublic void run() {while (true) {clerk.cusumerProduct();}}
}public class ProductTest {public static void main(String[] args) {Clerk c1 = new Clerk();Productor p1 = new Productor(c1);Customer cust = new Customer(c1);Customer cust2 = new Customer(c1);p1.setName("生产者");cust.setName("消费者1");cust2.setName("消费者2");p1.start();cust.start();cust2.start();}
}

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...