Java多线程(5)--线程通信wait和notify

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

解决:涉及wait()notify()/notifyAll()

class Communicate implements Runnable {private int number = 1;@Overridepublic void run() {while (true) {synchronized (this) {this.notify();if (number <= 100){System.out.println(Thread.currentThread().getName() + "打印出" + number);number++;try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}else break;}}}
}public class CommunicateTest {public static void main(String[] args) {Communicate communicate = new Communicate();Thread thread1 = new Thread(communicate);Thread thread2 = new Thread(communicate);thread1.setName("线程一");thread2.setName("线程二");thread1.start();thread2.start();}
}

wait():令当前线程挂起,放弃CPU、同步资源并等待,使别的线程可访问并修改共享资源,而当前线程排队等候其他线程调用notify()或notifyAll()方法唤醒,唤醒后等待重新获得对监视器的所有权后才能继续执行。

notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待。

notifyAll():唤醒正在排队等待资源的所有线程结束等待。

这三个方法只有在synchronized方法或synchronized代码块中才能使用,否则会报
java.lang.IllegalMonitorStateException异常。

这三个方法的调用者都必须是同步监视器,即如同步监视器.wait()。例如以上代码中的同步监视器是本对象this。

这三个方法是定义在Object类中的,而非Thread。


sleep() 和wait()的异同:

1.相同点:一 旦执行方法,都可以使得当前的线程进入阻塞状态。
2.不同点:①两个方法声明的位置不同: Thread类中声明sleep() ,Object类中声明wait()。②调用的要求不同: sleep() 可以在任何需要的场景下调用,wait( )必须使用在同步代码块或同步方法中。③关于是否释放同步监视器: 如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁。


经典例题:生产者/消费者问题

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

①店员(产品):

//店员(产品)
class Clerk {private int productNum = 0;public synchronized void addProduct() {if (productNum < 20){productNum++;System.out.println(Thread.currentThread().getName() + ":生产的第" + productNum + "个产品");notifyAll();}else {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}}public synchronized void getProduct() {if (productNum > 0){productNum--;System.out.println(Thread.currentThread().getName() + ":消费的第" + productNum + "个产品");notifyAll();}else {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}}
}

②生产者:

//生产者
class Productor implements Runnable {private Clerk clerk;public Productor(Clerk clerk) {this.clerk = clerk;}@Overridepublic void run() {System.out.println("生产者开始生产产品");while (true) {try {Thread.sleep((int) Math.random() * 1000);} catch (InterruptedException e) {e.printStackTrace();}clerk.addProduct();}}
}

③消费者:

//消费者
class Consumer implements Runnable {private Clerk clerk;public Consumer(Clerk clerk) {this.clerk = clerk;}public void run() {System.out.println("消费者开始取走产品");while (true) {try {Thread.sleep((int) Math.random() * 1000);} catch (InterruptedException e) {e.printStackTrace();}clerk.getProduct();}}
}

④主进程main

public class ProductTest {public static void main(String[] args) {Clerk clerk = new Clerk();Productor productor = new Productor(clerk);Consumer consumer = new Consumer(clerk);Thread thread1 = new Thread(productor);Thread thread2 = new Thread(consumer);thread1.setName("生产者");thread2.setName("消费者");thread1.start();thread2.start();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/347646.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab eig 复杂度,MATLAB中的eig函数

在MATLAB中&#xff0c;计算矩阵A的特征值和特征向量的函数是eig(A)&#xff0c;常用的调用格式有5种&#xff1a;Eeig(A)&#xff1a;求矩阵A的全部特征值&#xff0c;构成向量E。[V,D]eig(A)&#xff1a;求矩阵A的全部特征值&#xff0c;构成对角阵D&#xff0c;并求A的特征向…

spring常见面试问题_Spring面试问题

spring常见面试问题另外&#xff0c;请查看我们最新的文章69Spring面试问题与解答–最终清单 。 1&#xff09;什么是春天&#xff1f; 回答&#xff1a; Spring是控件和面向方面的容器框架的轻量级反转。 2&#xff09;解释春天&#xff1f; 回答&#xff1a; 轻巧&#x…

Java多线程(6)--Callable接口创建线程

与使用Runnable相比&#xff0c; Callable功能更强大些 ①相比run()方法&#xff0c;可以有返回值 ②方法可以抛出异常 ③支持泛型的返回值 ④需要借助FutureTask类&#xff0c;可以获取返回结果 Future接口 ①可以对具体Runnable、Callable任务的执行结果进行取消、查询是否完…

matlab谱系聚类图,如何看懂SPSS聚类分析的树状图/谱系图?

原创&#xff1a; 数据小兵 SPSS统计训练营SPSS聚类分析提供两种类别图形的输出&#xff0c;第一种是软件默认的“冰柱图”&#xff0c;形状类似于冬天屋檐上垂下的冰柱&#xff0c;因此得名。第二种是“树状图”&#xff0c;在新版本软件中也称谱系图&#xff0c;像一个横着生…

Java多线程(7)--线程池创建线程

经常创建和销毁、使用量特别大的资源&#xff0c;比如并发情况下的线程&#xff0c;对性能影响很大。 提前创建好多个线程&#xff0c;放入线程池中&#xff0c;使用时直接获取&#xff0c;使用完放回池中&#xff0c;可以避免频繁创建销毁、实现重复利用。 使用线程池好处&a…

在Google Cloud Platform的K8上运行Fn函数

最近&#xff0c;我在Functions和Project Fn中玩了很多游戏。 最终&#xff0c;我不得不离开笔记本电脑上的操场&#xff0c;进入真正的野生世界。 在K8s集群上运行Fn的想法对我来说很有吸引力&#xff0c;因此我决定在Prem或云中的某个地方进行操作。 在对如何在裸机上自行安装…

php判断对象属于哪个类,PHP instanceof:判断对象是否属于某个类

使用 PHP 中的 instanceof 运算符&#xff0c;可以判断一个对象是否属于某一个类&#xff0c;语法格式如下&#xff1a;对象名 instanceof 类名;【示例】使用 instanceof 判断一个对象是否属于某个类。class A{}class B{}$obj new A;var_dump($obj instanceof A);echo ;var_du…

Java常用类(1)--字符串相关类String、StringBuffer、StringBuilder全面知识

文章目录String类StringBuffer类StringBuilder类String&#xff1a;不可变的字符序列&#xff1b;底层使用char[]存储 StringBuffer&#xff1a;可变的字符序列&#xff1b;线程安全的&#xff0c;效率低&#xff1b;底层使用char[]存储 StringBuilder&#xff1a;可变的字符序…

hybbs接口php,HYBBS

#HYBBS官方地址: http://bbs.hyyyp.com论坛基于HYPHP框架开发MVC结构支持HOOK机制PDO操作SQL,支持众多数据库论坛特性服务器环境要求:支持子目录安装论坛PHP 5.3 包括5.3 , 5.3以上环境Apache || Nginx || IIS需要开启伪静态,否则无法安装~!数据库支持 : MYSQL , MSSQL ,Oracle…

Java常用类(2)--日期时间相关类Date、Calendar、LocalDateTime、Instant全面

文章目录java.lang.System类java.util.Date类java.sql.Date类java.text.SimpleDateFormat类java.util.Calendar(日历)类java.time类java.time.Instant类java.time.format.DateTimeFormatter 类其它APIjava.lang.System类 System类提供的public static long currentTimeMillis(…

apache camel_Apache Camel简介

apache camelApache Camel是著名的企业集成模式的开源实现。 Camel是一个路由和中介引擎&#xff0c;可帮助开发人员以各种特定于域的语言&#xff08;DSL&#xff09;&#xff08;例如Java&#xff0c;Spring / XML&#xff0c;scala等&#xff09;创建路由和中介规则。 骆驼…

oracle括号不区分中英,Oracle的sql语句,查询条件加括号与不加括号区别 -

例如:SELECT ename, job, deptnoFROM empWHERE deptno in (10, 20)AND (ename like ‘%I‘ OR job like ‘%ER‘);执行该sql&#xff0c;结果集如下&#xff1a;1 JONES MANAGER 202 CLARK MANAGER 10去掉上面sql查询条件中的括号&a…

Java常用类(3)--Java比较器Comparable、Comparator类

文章目录自然排序&#xff1a;java.lang.Comparable定制排序&#xff1a;java.util.Comparator自然排序&#xff1a;java.lang.Comparable Comparable接口强行对实现它的每个类的对象进行整体排序&#xff0c;这种排序被称为类的自然排序。 实现 Comparable 的类必须实现 com…

Angular5 JWT身份验证(Spring Boot安全性)

欢迎使用带有Spring Security的angular5 jwt身份验证。在本教程中&#xff0c;我们将在一个angular5单页应用程序中使用jwt身份验证创建一个完整的堆栈应用程序&#xff0c;该应用程序具有由spring boot支持并集成了spring security的后备服务器。带有集成了HttpInterceptor的示…

Java常用类(4)--System类

System类代表系统&#xff0c;系统级的很多属性和控制方法都放置在该类的内部&#xff0c;该类位于java.lang包。 由于该类的构造器是private的&#xff0c;所以无法创建该类的对象&#xff0c;也就是无法实例化该类。其内部的成员变量和成员方法都是static的&#xff0c;可以…

创新设计模式:原型模式

原型模式用于创建对象的副本。 这种模式非常有用&#xff0c;特别是当从头开始创建对象的成本很高时。 与builder &#xff0c; factory和abstract factory模式相比&#xff0c;它不会从头开始创建对象&#xff0c;而是会克隆/重新创建它。 与单例模式相比&#xff0c;它创建一…

oracle游标的实例,oracle游标实例

--游标----游标&#xff1a;当在PL/SQL块中执行查询语句和数据操作语句时&#xff0c;oracle会为其分配上下文区&#xff0c;游标是指向上下文区的指针。----显示游标&#xff1a;显示游标在PL/SQL块的声明部分声明&#xff0c;在执行部分或异常处理部分打开游标&#xff0c;提…

Java常用类(5)--不可变的任意精度BigInteger、BigDecimal类

文章目录BigInteger类BigDecimal类BigInteger类 Integer类作为int的包装类&#xff0c;能存储的最大整型值为2^31-1&#xff0c;Long类也是有限的&#xff0c; 最大为2^63-1。如果要表示再大的整数&#xff0c;不管是基本数据类型还是他们的包装类 都无能为力。 java.math包的…

创新设计模式:单例模式

单例设计模式是一种软件设计模式&#xff0c;用于将类的实例化限制为一个对象。 与其他创建设计模式&#xff08;例如抽象工厂 &#xff0c; 工厂和构建器模式&#xff09;相比&#xff0c;单例将创建一个对象&#xff0c;但也将负责&#xff0c;因此该对象只有一个实例存在。…

UNIX下 oracle expdp,Linux服务器下对Oracle数据库expdp(导出)和impdp(导入)

Linux服务器下对Oracle数据库expdp(导出)和impdp(导入)紧接上篇文章&#xff0c;Oracle数据库架构已经创建完成&#xff0c;我的需求是&#xff1a;将老服务器上的数据库迁移到新的数据库上。这就用到impdp(导入)操作。要想实现对新数据库的impdp(导入)工作&#xff0c;首先需要…