Java——线程协作(1)

线程协作

在之前的多线程并发执行的学习中,是多条线程同时执行,他们相互抢夺cpu的控制权,谁先抢夺到谁先执行,这样的并行机制带有随机性,也就是说,多条线程并发时,谁先谁后是不确定的,但是有时候,我们希望多条线程之间能够共同协作来完成一个任务,这样子这些线程之间势必存在通信关系,而不能你做你的,我做我的,最后无法达到共同目的,所以java提供了一种线程协作的机制

首先,先给出一个例子来更好的解释线程协作这个概念,假设现在有一个生产者,一个消费者,消费者负责吃生产者生产的苹果,生产者负责生产消费者想要的苹果,这样生产者和消费者在披萨方面建立起了依赖关系
生产和消费之间存在了联系,不能再是之前那种线程并发执行那样,随机生产、随机消费,所以我们要用到线程协作的机制,当仓库空了的时候,让消费者等待,而生产者生产,生产者生产完了之后,马上唤醒消费者说可以消费了,而一旦仓库满了,就让生产者等待,消费者继续消费,消费者消费了之后仓库就会空余出来,这时候又可以通知生产者进行生产,如此往复,生产者和消费者之间互相依赖,协调控制

  • 生产者
  • 消费者

为了实现上面所说的这个目的,我们要学习一种机制,叫做——等待唤醒机制


等待唤醒机制

  • wait:线程不再活动,不再参与调度,进入wait set中,因此不会浪费CPU资源,也不会去竞争锁,线程必须等待别的线程执行一个特别的动作(“notify”),通知该线程从wait set中释放出来,重新进入到调度队列中
  • notify:选取所通知对象的wait set中的一个线程释放
package LinkCoorperation;

import javax.swing.plaf.TableHeaderUI;

public class TestPC {
    public static void main(String[] args) {
        Contain contain = new Contain();
        Custom custom = new Custom(contain);
        Producer producer = new Producer(contain);

        producer.start();
        custom.start();

    }
}

class Apple{
    int ID;

    public Apple(int ID){
        this.ID = ID;
    }
}

//容器
class Contain{
    private Apple[] apples = new Apple[10];
    int count = 0;

    //生产者生产苹果
    public synchronized void push(Apple apple){
        if(count==apples.length){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
            //生产东西
            apples[count] = apple;
            count++;
            //生产东西之后,通知消费者来消费
            this.notify();
    }

    //消费者消费苹果
    public synchronized Apple pop(){
        //消费完了,不要再消费了
        if(count==0) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //用于使消费者不要那么被唤醒,等生产者打印出那句“生产者生产了....”再消费
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //消费者消费东西
            count--;

            //消费者消费了东西,通知生产者生产
            this.notify();
            return apples[count];
    }
}

//生产者
class Producer extends Thread{
    Contain contain;

    public Producer(Contain contain){
        this.contain = contain;
    }

    public void run(){
        for (int i = 1; i < 100; i++) {
            contain.push(new Apple(i));
            System.out.println("生产者生产了" + i + "个苹果");
        }
    }
}

//消费者
class Custom extends Thread{
    Contain contain;

    public Custom(Contain contain){
        this.contain = contain;

    }

    public void run(){
        for (int i = 1; i < 100; i++) {
            System.out.println("消费者吃掉了第"+ contain.pop().ID + "个苹果");
        }
    }
}
        //用于使消费者不要那么被唤醒,等生产者打印出那句“生产者生产了....”再消费
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

在我举的例子里面,我在消费者消费之前加了一段等待的代码,原因是我再进行测试的时候,发现生产者生产完产品之后唤醒消费者消费的时候,消费者速度实在太快了,以至于程序中生产者的for循环里面,还没来的及打印“生产者生产了…”就先完成了消费者的消费,也就是说程序先打印出了"消费者消费了…",以至于逻辑上感觉不对,所以我为了放大问题的发生性,我加了这个延迟的sleep代码段,一般来说,这段代码加与不加没有什么影响

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值