1. 线程通信
1. 应用场景:生产者和消费者问题
- 假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中的产品取走
- 如果仓库中没有产品,则身缠这将产品放入到仓库中,否则停止生产并等待,直到仓库中的产品被消费者取走为止
- 如果仓库中放有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中再次放入产品为止
2.线程通信分析
这是一个线程同步的问题,生产者和消费者共享同一个资源,并且生产者和消费者之家相互依赖,虎威条件
- 对于生产者,没有生产产品之前,要通知消费者等待。而生产产品只有,有需要马上通知消费者消费
- 对于消费者,在消费之后,要通知生产者已经结束消费,需要生产新的产品以供消费
- 在生产者和消费者问题中仅有synchronized是不都的。
- synchronized课阻止并发更新同一个共享资源,实现了同步
- synchronized不能用来实现不同线程之间的消息传递
3. 通信解决问题的方法
方法名 | 作用 |
---|---|
wait() | 表示线程一致等待,直到其他线程通知,与sleep不同,会释放锁 |
wait(long timeout) | 指定等的毫秒数 |
notify() | 唤醒一个处于等待状态的线程 |
notifyAll() | 唤醒一个对象上所有调用wait()方法的线程,优先级别高的线程优先调度 |
2. 解决方式
1.并发协作模“消费者/生产者”—》管理法
- 生产者:负责生产数据的模块(可能是方法、对象、进程)
- 消费者:负责处理数据的模块(可能是方法、对象、进程)
- 缓冲区:消费者不能直接使用生产者的数据,他们之间有个缓冲区
package Demo06;
/*
测试:
并发协作模“消费者/生产者”---》利用缓冲区解决:管理法
生产者、消费者、缓冲区、产品
*/
public class TestPC {
public static void main(String[] args) {
Container container = new Container();
new Producer(container).start();
new Consummer(container).start();
}
}
//生产者
class Producer extends Thread{
Container container;
public Producer(Container container) {
this.container = container;
}
//生产
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("生产了"+i);
container.push(new Product(i));
}
}
}
//消费者
class Consummer extends Thread{
Container container;
public Consummer(Container container) {
this.container = container;
}
//消费
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了"+i);
container.pop();
}
}
}
//产品
class Product{
int id;//产品id
public Product(int id) {
this.id = id;
}
}
//缓冲区
class Container{
//需要定义一个容器大小
Product[] products = new Product[10];
int count =0;//容器计数
//生产者放入产品
public synchronized void push(Product product){
//如果容器是否满了,提醒消费者取出
if(count==products.length){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果未满,继续放
products[count] = product;
count++;
//通知消费者可以消费了
this.notifyAll();
}
//消费者取出产品
public synchronized Product pop(){
//如果容器中没有产品,提醒生产者生产
if(count<=0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果容器中有商品,取出
count--;
Product product = products[count];
//通知生产者可以生产
this.notifyAll();
return product;
}
}
2.并发协作模“消费者/生产者”—》信号灯法
package Demo06;
/*
测试2:
生产者/消费者----》标志位解决法:信号灯法
*/
public class TestPC2 {
public static void main(String[] args) {
Product1 product1 = new Product1();
new Producer1(product1).start();
new Consummer1(product1).start();
}
}
//生产者
class Producer1 extends Thread{
Product1 product1;
public Producer1(Product1 product1) {
this.product1 = product1;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
this.product1.Product("race");
}
}
}
//消费者
class Consummer1 extends Thread{
Product1 product1;
public Consummer1(Product1 product1) {
this.product1 = product1;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
this.product1.Consumme();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//产品
class Product1{
/*
生产者生产,消费者等待
消费者消费,生产者等待
*/
String food;//生产的产品
boolean flag = false;
//生产
public synchronized void Product(String food){
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("生产了"+food);
//通知消费者消费
this.notifyAll();
this.food = food;//更新产品
this.flag = !this.flag;
}
//消费
public synchronized void Consumme() throws InterruptedException {
if(flag){
System.out.println("吃了"+food);
this.notifyAll();
this.flag = !this.flag;
}else{
this.wait();
}
}
}