个人主页:Dawn黎明开始

系列专栏:Java
每日一句:什么都不做,才会来不及

欢迎大家:关注+点赞+评论+收藏⭐️


文章目录

多线程通信

(1).由来

(2).成员方法

(3).案例引入

(4).代码实现



多线程通信

(1).由来

现代社会崇尚合作精神,分工合作在日常生活和工作中无处不在。举个简单的例子,例如一条生产线的上下两个工序,它们必须以规定的速率完成各自的工作,才能保证产品在流水线中顺利的流转。如果下工序过慢,会造成产品在两道工序之间的积压,如果上工序过慢,会造成下工序长时间无事可做。在多线程的程序中,上下工序可以看作两个线程,这两个线程之间需要协同完成工作,就需要线程之间进行通信。

思路:

如果想解决上述线程执行不一致的问题,就需要控制多个线程按照一定的顺序轮流执行,此时就需要让线程间进行通信保证线程任务的协调进行

解决:

为此,Java在Object类中提供了wait()notify()notifyAll()等方法用于解决线程间的通信问题,因为Java中所有类都是Object类的子类或间接子类,因此任何类的实例对象都可以直接使用这些方法。

(2).成员方法

说明:

其中wait()方法用于使当前线程进入等待状态,notify()和notifyAll()方法用于唤醒当前处于等待状态的线程。

注意:

wait()、notify()和notifyAll()方法的调用者都应该是同步锁对象,如果这三个方法的调用者不是同步锁对象,Java虚拟机就会抛出IllegalMonitorStateException异常

(3).案例引入

生产者-消费者问题分析:

资源:product<=20

前台店员:Clerk

A:从生产者线程获取资源

B:将资源卖给消费者线程

生产资源:ProducerThread(生产者)

消费资源:ConsumerThread(消费者)

测试类:Demo

(4).代码实现

分析:

A:使用同步机制

B:线程通信问题:通过Java提供的等待唤醒机制解决。

Object类中提供了三个方法:

wait():等待,释放锁资源

notify():唤醒单个线程,从等待的位置继续执行

notifyAll():唤醒所有线程

代码如下

package Pro;public class Clerk {private int product=20; //共享资源//从生产者线程获取资源public synchronized void addProduct(){if(product>=20){try {this.wait();//生产者线程等待,释放锁资源} catch (InterruptedException e) {e.printStackTrace();}}else{product++;System.out.println("生产者生产第" + product + "个产品");this.notifyAll();}}//将资源卖给消费者线程public synchronized void sellProduct(){if(product<=0){try {this.wait();//消费者线程等待,释放锁资源} catch (InterruptedException e) {e.printStackTrace();}}else{System.out.println("消费者消费第"+product+"个产品");product--;this.notifyAll();}}}
package Pro;public class ProducerThread implements Runnable {Clerk clerk;public ProducerThread(Clerk clerk) {super();this.clerk = clerk;}@Overridepublic void run() {while(true){clerk.addProduct();try {Thread.sleep((int)(Math.random()*10)*100);} catch (InterruptedException e) {e.printStackTrace();}}}}
package Pro;public class ConsumerThread implements Runnable {Clerk clerk;public ConsumerThread(Clerk clerk) {super();this.clerk = clerk;}@Overridepublic void run() {while(true){clerk.sellProduct();try {Thread.sleep((int)(Math.random()*10)*100);} catch (InterruptedException e) {e.printStackTrace();}}}}

package Pro;public class Demo {public static void main(String[] args) {Clerk c=new Clerk();new Thread(new ProducerThread(c), "生产者线程甲").start();new Thread(new ProducerThread(c), "生产者线程乙").start();new Thread(new ConsumerThread(c),"消费者线程甲").start();new Thread(new ConsumerThread(c),"消费者线程乙").start();//ProducerThread pt =new ProducerThread(c);//Thread t1=new Thread(pt, "生产者线程甲");//Thread t2=new Thread(pt, "生产者线程乙");//ConsumerThread ct =new ConsumerThread(c);//Thread t3=new Thread(ct,"消费者线程甲");//Thread t4=new Thread(ct,"消费者线程乙");//t1.start();//t2.start();//t3.start();//t4.start();}}

思考:

为什么这些方法不定义在Thread类而是Object类中呢” />锁对象调用,而Object类对象代表任意的对象。所以,这些方法必须定义在Object类中。


建议大家亲自动手操作,学编程,多实践练习是提升编程技能的必经之路。

欢迎大家在评论区进行讨论和指正!