Java语言之线程间的通信

一,线程的五种状态

1,NEW:至今尚未启动的线程处于这种状态。
2,RUNNABLE: 正在Java虚拟机上运行的线程处于这种状态。
3,BLOCKED:阻塞状态,受阻塞并等待某个监视器锁的线程处于这种状态。
4,TIMED_WAITING:休眠(睡眠)状态,计时等待。
5,WAITING:无限期等待另一个线程来执行某一特定操作(notify)的线程处于这种状态。
6,TERMINATED:已退出的线程处于这种状态。

在这里插入图片描述

二,Waiting(无线等待状态)

线程间通信概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。

如何保证线程间通信有效利用资源
多个线程在处理同一个资源,并且任务不同时,需要线程通信来帮助解决线程之间对同一个变量的使用或操作。 就
是多个线程在操作同一份数据时, 避免对同一共享变量的争夺。也就是我们需要通过一定的手段使各个线程能有效
的利用资源。而这种手段即—— 等待唤醒机制

等待唤醒机制案例(线程之间的通信):
1,创建一个顾客线程(消费者):其中调用wait方法,放弃CPU的执行,进入到waiting状态(无限等待)。
2,创建一个老板线程(生产者):调用notify方法,唤醒消费者。

注意事项
1,消费者及生产者线程必须都使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行;
2,同步使用的锁对象必须保证唯一
3,只有锁对象才能调用wait和notify方法。

Object类中的方法:
void wait():在其他线程调用此对象的notify或者notifyAll方法之前,导致当前线程等待。
void notify():唤醒此对象监视器上等待的单线程,会继续执行wait方法之后的代码;若有多个线程会随机唤醒一个。
void notifyAll():唤醒对象监视器上的所有线程。

public class DemoWaitAndNotify {
    public static void main(String[] args) {
        Object obj = new Object();

        new Thread(){
            @Override
            public void run() {
                while (true){
                    synchronized (obj){
                        System.out.println("顾客1:告知老板需要包子的数量");
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("顾客1:开始吃包子");
                        try {
                            Thread.sleep(4000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("顾客1:吃完包子了");
                        System.out.println("-------------------");
                    }
                }
            }
        }.start();

        Runnable rt = new Runnable(){
            @Override
            public void run() {
                while (true){
                    synchronized (obj){
                        System.out.println("顾客2:告知老板需要包子的数量");
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("顾客2:开始吃包子");
                        try {
                            Thread.sleep(4000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("顾客2:吃完包子了");
                        System.out.println("-------------------");
                    }
                }
            }
        };
        new Thread(rt).start();

        new Thread(){
            @Override
            public void run() {
                while (true){
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (obj){
                        System.out.println("老板:开始做包子...");
                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("老板:做好包子了");
//                        obj.notify();
                        /*
                            顾客1:告知老板需要包子的数量
                            顾客2:告知老板需要包子的数量
                            老板:开始做包子...
                            老板:做好包子了
                            顾客1:开始吃包子
                            顾客1:吃完包子了
                            -------------------
                            顾客1:告知老板需要包子的数量
                            老板:开始做包子...
                            老板:做好包子了
                            顾客2:开始吃包子
                            顾客2:吃完包子了
                            -------------------
                         */
                        obj.notifyAll();
                        /*
                            顾客1:告知老板需要包子的数量
                            老板:开始做包子...
                            老板:做好包子了
                            顾客2:告知老板需要包子的数量
                            顾客1:开始吃包子
                            顾客1:吃完包子了
                            -------------------
                            顾客1:告知老板需要包子的数量
                            老板:开始做包子...
                            老板:做好包子了
                            顾客2:开始吃包子
                            顾客2:吃完包子了
                            -------------------
                         */
                    }
                }
            }
        }.start();
    }
}

注意:哪怕只通知了一个等待的线程,被通知线程也不能立即恢复执行,因为它当初中断的地方是在同步块内,而此刻它已经不持有锁,所以它需要再次尝试去获取锁(很可能面临其它线程的竞争),成功后才能在当初调用 wait 方法之后的地方恢复执行。

三,消费者生产者模型

等待唤醒机制其实就是经典的“生产者与消费者”的问题。
共享资源

public class BaoZi {
    public String pi;
    public String xian;
    public Boolean state = false;
}

生产者

public class DemoProduce extends Thread {
    private BaoZi bz;

    public DemoProduce(BaoZi bz) {
        this.bz = bz;
    }

    @Override
    public void run() {
        int count = 0;
        while (true){
            synchronized (bz){
                if (bz.state == false){
                    if (count%2 == 0){
                        bz.pi = "冰皮";
                        bz.xian = "韭菜";
                    }else{
                        bz.pi = "薄皮";
                        bz.xian = "牛肉";
                    }
                    bz.state = true;
                    count++;
                }
                System.out.println("老板:正在生产"+bz.pi+bz.xian+"陷包子");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("老板:做好"+bz.pi+bz.xian+"陷包子");
                bz.notify();

                if (bz.state == true){
                    try {
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

消费者

public class DemoConsume extends Thread {
    private BaoZi bz;

    public DemoConsume(BaoZi bz) {
        this.bz = bz;
    }

    @Override
    public void run() {
        while (true){
            synchronized (bz){
                if (bz.state == false){
                    try {
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }

                //被唤醒之后
                System.out.println("顾客:开始吃"+bz.pi+bz.xian+"陷包子");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("顾客:吃完"+bz.pi+bz.xian+"陷包子了");
                bz.state = false;
                System.out.println("-------------------");

                bz.notify();
            }
        }
    }
}

测试类:

public class DemoTest {
    public static void main(String[] args) {
        BaoZi bz = new BaoZi();
        DemoConsume con = new DemoConsume(bz);
        DemoProduce pro = new DemoProduce(bz);
        con.start();
        pro.start();
        /*
        老板:正在生产冰皮韭菜陷包子
        老板:做好冰皮韭菜陷包子
        顾客:开始吃冰皮韭菜陷包子
        顾客:吃完冰皮韭菜陷包子了
        -------------------
        老板:正在生产薄皮牛肉陷包子
        老板:做好薄皮牛肉陷包子
        顾客:开始吃薄皮牛肉陷包子
        顾客:吃完薄皮牛肉陷包子了
        -------------------
        老板:正在生产冰皮韭菜陷包子
        老板:做好冰皮韭菜陷包子
        顾客:开始吃冰皮韭菜陷包子
        顾客:吃完冰皮韭菜陷包子了
        -------------------
         */
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值