*阿炮的Java笔记014号*-多线程的通信问题

文章讨论了多线程环境下线程通信的重要性,特别是等待唤醒机制,包括wait(),notify()和notifyAll()方法的使用。通过生产者消费者问题举例,展示了如何在Java中实现线程间的协作。同时提到了可能的性能问题,如频繁的等待与唤醒操作,以及sleep()与wait()的区别。
摘要由CSDN通过智能技术生成

老生常谈…对于大佬们根本都不用看的博客!

对于像我这种菜鸡还是得一步一步的来!如果有错误请大佬们指点指点!

线程通信

为什么要线程通信呢?

多线程在处理同一个资源的时候,处理的方法不同。

当多个线程并发执行时,CPU时随机切换线程的,当我们需要多个线程来同时完成一件事的时,我们希望这些线程能够有规律的执行,所有产生了一些通信机制来协调它们来完成工作。

线程之间的线程通信的机制被称为:等待唤醒机制。

等待唤醒机制

等待唤醒机制就是一个线程在完成一件操作后进入等待状态,然后等待其他线程执行后再将其唤醒,也可以通过指定时间,自动唤醒。

一般用三种方法实现:

  • wait():让线程进入等待状态;
  • notify():唤醒正在等待中里优先级最高的线程;
  • notifyAll():唤醒所有等待中的线程;

注意:

  • 线程被唤醒后不一定立即执行,因为它只有成功获取了锁后才能正常运行。成功获得锁后,可以等待执行,反之则继续等待。
  • wait和notify必须由同一个对象调用;
  • wait和notify属于Object类,是对象的方法;
  • wait和notify必须要在同步代码块或同步方法中使用;

通过描述可知,线程通信就相当于一个线程负责生产,一个线程负责消费,生产成功后通知消费者消费。

生产者与消费者

因此线程安全和线程通信是这个代码问题的两个难点

废话不多说直接上代码:

物品

//物品
public class Goods {
    //物品数量
    int count;
    //是否生产完成
    boolean flag;

    public synchronized void produce() {
        if (this.flag) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.count++;
        System.out.println("生产第" + this.count + "个");
        this.flag = true;
        this.notify();
    }

    public synchronized void consume() {
        // flag为false,消费完成,等待生产
        if (!this.flag) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("消费第" + this.count + "个");
        this.flag = false;
        this.notify();
    }
}

生产者

//生产者
public class Product implements Runnable {
    private  final  Goods goods;

    public Product(Goods goods) {
        this.goods = goods;
    }


    @Override
    public void run() {
        while (true) {
            this.goods.produce();
        }
    }
}

消费者

//消费者
public class Consume implements Runnable{
    private  final  Goods goods;

    public Consume(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
        while (true) {
            this.goods.consume();
        }
    }
}

测试

//测试类
public class Test {
    public static void main(String[] args) {
        Goods goods = new Goods();
        Consume consume = new Consume(goods);
        Product product = new Product(goods);
        Thread consumeThread = new Thread(consume);
        Thread productThread = new Thread(product);
        consumeThread.start();
        productThread.start();
    }
}

可能出现的性能问题

  • 频繁等待与唤醒,导致JVM 和 操作系统交互的次数过多;
  • notifyAll() 唤醒全部的线程,也浪费线程资源,不要因为一个线程而唤醒所有线程;

sleep()和wait()的区别

  • sleep() 不释放锁,wait() 释放锁;
  • leep() 指定休眠的时间,wait() 可以指定时间也可以无限等待直到调用 notify() 或 notifyAll()
  • sleep( )在 Thread 类中声明的静态方法,wait 方法在 Object 类中方法;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

史上最菜的山炮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值