三、Java多线程编程 (线程间通信)
2020-12-14 本文已影响0人
大虾啊啊啊
1、等待和通知机制(wait、notify)
wait()方法
使当前执行代码的线程进入等待的状态,该方法是Object类的方法,使当前线程进入预执行队列,使用wait()方法前,必须拿到对象级别的锁,即只能在同步方法里执行,执行wait方法之后会释放锁,线程进入了等待的状态。
notify方法
和wait方法一样,同样要拿到对象级别的锁,也就是只能在同步方法内执行。notify的作用是通知调用wait方法进入等待的线程,恢复执行。调用notify方法之后,不会立即释放锁,程wait状态的线程也不会立即拿到锁,只有调用notify方法的线程执行完同步方法之后,才会释放锁。释放锁完之后,当执行wait方法的线程拿到锁之后,就会恢复执行。
notifyAll方法
如果有多个线程调用了wait方法,只调用notify通知,则是随机通知某一个线程恢复执行,如果想要通知全部线程,则调用notifyAll方法
wait和sleep的区别
相同点:wait和sleep都会使当前线程暂停执行
不同点:
1、wait是Object类的方法,而sleep是Thread的方法
2、wait的执行必须要拿到对象级别的锁,也就是必须在同步方法里执行,而sleep不是必须的。
3、wait执行完之后,会立即释放锁,使得当前线程暂停执行。而sleep方法虽然是使得当前线程暂停执行,不会释放锁,也就是说当sleep执行在同步方法里的时候,会使得当前线程进入阻塞的状态。
2、生产者和消费者模式(实现线程之间的通信)
生产者
package com.company;
import java.util.Date;
/**
* 生产者
*/
public class ProductThread extends Thread {
private Goods goods;
public ProductThread(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
super.run();
while (true) {
productGoods();
}
}
/**
* 生产商品
*/
private void productGoods() {
synchronized (goods) {
try {
//如果商品还没被消费,则先等被消费
if (goods.getName() != null) {
goods.wait();
}
//如果已经被消费了,则生产商品
goods.setName(new Date().getTime() + "");
System.out.println("生产商品:" + goods.getName());
//通知消费
goods.notify();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
消费者
package com.company;
/**
* 消费者
*/
public class ConsumerThread extends Thread {
//消费商品
private Goods goods;
public ConsumerThread(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
super.run();
while (true) {
cosumerGoods();
}
}
/**
* 消费商品
*/
private void cosumerGoods() {
synchronized (goods) {
try {
//如果商品还没被生产,则先等生产
if (goods.getName() == null) {
goods.wait();
}
System.out.println("消费商品:" + goods.getName());
//如果商品已经生产了,直接消费商品
goods.setName(null);
//通知生产
goods.notify();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
商品
package com.company;
/**
* 商品类
*/
public class Goods {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试
package com.company;
public class MyMain {
public static void main(String[] args) {
Goods goods = new Goods();
ProductThread productThread = new ProductThread(goods);
ConsumerThread consumerThread = new ConsumerThread(goods);
productThread.start();
consumerThread.start();
}
}
结果
生产商品:1607925851349
消费商品:1607925851349
生产商品:1607925853350
消费商品:1607925853350
生产商品:1607925855351
消费商品:1607925855351
生产商品:1607925857351
消费商品:1607925857351
生产者消费者模型分析
- 生产者生产商品,当发现商品还没有被消费的时候,则进入等待状态。如果商品已经被消费没有了,则生产商品,通知消费者消费。
- 消费者消费商品,当发现商品还没有被生产的时候,则进入等待状态。如果商品已经被生产了,则消费商品,通知生产者继续生产商品。
- 生产者和消费者都需要对商品进行加锁,防止线程安全问题。