Java中的线程间通信
时间:2020-07-12
本文章向大家介绍Java中的线程间通信,主要包括Java中的线程间通信使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Java 多线程
]
什么是Polling 以及它有什么问题?
重复测试条件直到它变为真的过程称为轮询Polling 。
轮询通常在循环的帮助下实现,以检查特定条件是否为真。如果是,则采取某些行动。这浪费了许多CPU周期并使实现效率低下。
例如,在一个经典的排队问题中,一个线程正在生成数据而另一个正在使用它。
Java多线程如何解决这个问题?
为了避免轮询,Java使用三种方法,即wait(),notify()和notifyAll()。
所有这些方法都属于对象类,因此所有类都有它们。它们必须仅在同步块中使用。
- wait() -它告诉调用线程放弃锁定并进入休眠状态,直到某个其他线程进入同一个监视器并调用notify()。
- notify() -它唤醒一个在同一个对象上调用wait()的线程。应该注意的是,调用notify()实际上并没有放弃对资源的锁定。
- notifyAll() -它唤醒在同一个对象上调用wait()的所有线程。
一个简单的Java程序来演示这三种方法 -
请注意,这个程序可能只在离线IDE中运行,因为它包含在几个点上输入。
// Java program to demonstrate inter-thread communication // (wait(), join() and notify()) in Java import java.util.Scanner; public class threadexample { public static void main(String[] args) throws InterruptedException { final PC pc = new PC(); // Create a thread object that calls pc.produce() Thread t1 = new Thread(new Runnable() { @Override public void run() { try { pc.produce(); } catch(InterruptedException e) { e.printStackTrace(); } } }); // Create another thread object that calls // pc.consume() Thread t2 = new Thread(new Runnable() { @Override public void run() { try { pc.consume(); } catch(InterruptedException e) { e.printStackTrace(); } } }); // Start both threads t1.start(); t2.start(); // t1 finishes before t2 t1.join(); t2.join(); } // PC (Produce Consumer) class with produce() and // consume() methods. public static class PC { // Prints a string and waits for consume() public void produce()throws InterruptedException { // synchronized block ensures only one thread // running at a time. synchronized(this) { System.out.println("producer thread running"); // releases the lock on shared resource wait(); // and waits till some other method invokes notify(). System.out.println("Resumed"); } } // Sleeps for some time and waits for a key press. After key // is pressed, it notifies produce(). public void consume()throws InterruptedException { // this makes the produce thread to run first. Thread.sleep(1000); Scanner s = new Scanner(System.in); // synchronized block ensures only one thread // running at a time. synchronized(this) { System.out.println("Waiting for return key."); s.nextLine(); System.out.println("Return key pressed"); // notifies the produce thread that it // can wake up. notify(); // Sleep Thread.sleep(2000); } } } }
输出:
producer thread running Waiting for return key. Return key pressed Resumed
虽然看起来很怪异,但如果你经历两次它真的是小菜一碟。
- 在主类中创建一个新的PC对象。
- 它使用两个不同的线程即t1和t2运行生成和使用PC对象的方法,并等待这些线程完成。
让我们了解我们的产品和消费方法是如何工作的。
- 首先,使用synchronized块可确保一次只运行一个线程。此外,由于在消耗循环开始时存在一个sleep方法,因此生成线程获得kickstart。
- 在produce方法中调用wait时,它会做两件事。首先,它释放它在PC对象上的锁定。其次,它使生成线程进入等待状态,直到所有其他线程终止,也就是说它可以再次获取PC对象的锁定,并且其他一些方法通过在同一对象上调用notify或notifyAll来唤醒它。
- 因此我们看到,一旦调用wait,控件就转移到使用线程并打印 - “等待返回键”。
- 按下返回键后,consume方法调用notify()。它还做了两件事 - 首先,与wait()不同,它不会释放对共享资源的锁定,因此为了获得所需的结果,建议仅在方法结束时使用notify。其次,它通知等待的线程现在它们可以唤醒,但只有在当前方法终止后才能唤醒。
- 正如您可能已经观察到的那样,即使在通知之后,控件也不会立即转移到生产线程。原因是我们在notify()之后调用了Thread.sleep()。正如我们已经知道消费线程在PC对象上持有一个锁,另一个线程在释放锁之前无法访问它。因此,只有在消费线程完成其休眠时间并且此后自行终止之后,产生线程才能收回控制。
- 暂停2秒后,程序终止完成。
如果您仍然对我们在使用消费线程中使用notify的原因感到困惑,请尝试删除它并再次运行程序。正如您现在必须注意到的,该程序永远不会终止。
原因很简单 - 当您在生产线程上调用wait时,它继续等待并且从未终止。由于程序运行直到其所有线程都已终止,因此它会一直运行。
这个问题还有第二种方法。您可以使用wait()的第二个变体。
void wait(long timeout)
这将使调用线程仅在指定的时间内休眠。
Java 多线程原文地址:https://www.cnblogs.com/breakyizhan/p/13287111.html
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 【Rust日报】2020-07-30 fixed_vec减少Rust数组冗余边界检查
- 我的小工具,用C和python实现远程读卡器,远程读写消费卡片
- c语言实现TCP的socket通信
- 多文件目录Makefile的写法
- 一个有趣的例子带你入门canvas
- GitLab 12 跨版本 13 升级
- 【Rust日报】2020-07-28 SO:在命令行下浏览StackOverflow
- 【翻译】200行代码讲透RUST FUTURES (6)
- MPU6050姿态解算方式1-DMP
- 打卡群刷题总结0729——分隔链表
- 单细胞tSNE细胞降维图还可以这样做?!
- 从IIC实测波形入手,搞懂IIC通信
- FreeRTOS例程4-串口DMA收发不定长数据
- FreeRTOS例程3-串口中断接收不定长的数据与二值信号量的使用
- 前端如何将json数据导出为excel文件