线程通信

线程通信

线程通讯指的是多个线程通过消息传递实现相互牵制,相互调度,即线程间的相互作用。

涉及三个方法:
.wait一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。
.notify一旦执行此方法,就会唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的那个。
.notifyAll一旦执行此方法,就会唤醒所有被wait的线程。
说明:
.wait(),notify(),notifyAll()三个方法必须使用在同步代码块或同步方法中。
.wait(),notify(),notifyAll()三个方法是定义在java.lang.Object类中

创建两个线程,分别命名为线程一、线程二,使之交替打印1-100的数。

public class Wait_Thread extends Thread{
    static int num = 1;
    static Object obj=new Object();
    @Override
    public void run() {
        while (true){
            synchronized (obj){
                obj.notify();
                if(num<=100) {
                    System.out.println(Thread.currentThread().getName() +num++);
                }else {
                    break;
                }
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
public class Wait_Test {
    public static void main(String[] args) {
        Wait_Thread wt1 = new Wait_Thread();
        wt1.setName("线程1:");
        Wait_Thread wt2 = new Wait_Thread();
        wt2.setName("线程2:");
        wt1.start();
        wt2.start();
    }
}

经典例题:生产者/消费者问题
生产者(Productor)将产品放在柜台(Counter),而消费者(Customer)从柜台处取走产品,生产者一次只能生产固定数量的产品(比如:1), 这时柜台中不能再放产品,此时生产者应停止生产等待消费者拿走产品,此时生产者唤醒消费者来取走产品,消费者拿走产品后,唤醒生产者,消费者开始等待.

import java.util.Random;

public class Counter_Thread extends Thread{
    static int counter = 5;
    static Object obj = new Object();
    Random random = new Random();
    @Override
    public void run() {
        while (true){
            synchronized (obj){
                if(counter>0){
                    obj.notify();
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    int a = random.nextInt(2);
                    if(counter<a+1){
                        System.out.println("消费者需要"+(a+1)+"件产品,柜台产品量为"+counter+"件,最终消费者拿走了所以的产品,目前还剩0件产品!");
                        counter-=counter;
                    }else {
                    counter-=(a+1);
                    System.out.println(Thread.currentThread().getName()+"拿了"+(a+1)+"件产品,目前还剩"+counter+"件产品!");}
                    if(counter==0){
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }else {
                    obj.notify();
                    int s = random.nextInt(5);
                    counter+=(s+5);
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"往柜台放"+(s+5)+"了件产品,目前还剩"+counter+"件产品");
                    if(counter>0){
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}
public class Counter_Test {
    public static void main(String[] args) {
        Counter_Thread counter_thread1 = new Counter_Thread();
        counter_thread1.setName("消费者");
        counter_thread1.start();
        Counter_Thread counter_thread2 = new Counter_Thread();
        counter_thread2.setName("生产者");
        counter_thread2.start();
    }
}

在实现柜台摆放时,个人认为重点并不是加锁的位置,而是释放锁的位置,当柜台的产品量为0时,则此时处于缺货状态,这时就应该让消费者线程等待,让出CPU使用权,并释放锁,让生产者线程获取CPU使用权,并拿到锁并执行放置产品行为,当产品在柜台的数量大于0时,此时让生产者线程等待,并且释放等待区的消费者线程,当消费者把柜台产品数量拿为零时,继续时消费者线程等待,并释放等待区的生成者,以此循环下去。

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值