Java多线程知识点总结——进阶篇(七) 之 等待唤醒机制

1、线程的通信方式通信:
其实就是多个线程在操作同一个资源,但是操作的动作不同。
2、API介绍
Object.wait():在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
Object.notify():唤醒在此对象监视器上等待的单个线程。
Object.notifyAll():唤醒在此对象监视器上等待的所有线程。

先来实现一个需求:
有两个线程,一个往资源池中生产数据,一个从资源池中消费数据
代码如下:

class Res {
    private String name;
    private String sex;
    private boolean flag = false; //用来判断有没有数据

    /**
     * 生产一条数据
     * @param name
     * @param sex
     */
    public synchronized void set(String name, String sex) {
        if (flag)
            try {this.wait();} catch (Exception e) {}

        this.name = name;
        this.sex = sex;
        flag = true;
        this.notify(); //唤醒另一个线程
    }

    /**
     * 消费数据
     */
    public synchronized void out() {
        if (!flag)
            try {this.wait();} catch (Exception e) {}

        System.out.println(name + "........" + sex);
        flag = false;
        this.notify();
    }
}

class Input implements Runnable {
    private Res r;

    Input(Res r) {
        this.r = r;
    }
    public void run() {
        int x = 0;
        while (true) {
            if (x == 0)
                r.set("mike", "man");
            else
                r.set("丽丽", "女女女女女");
            x = (x + 1) % 2;
        }
    }
}

class Output implements Runnable {
    private Res r;

    Output(Res r) {
        this.r = r;
    }

    public void run() {
        while (true) {
            r.out();
        }
    }
}

class InputOutputDemo2 {
    public static void main(String[] args) {
        Res r = new Res();

        new Thread(new Input(r)).start();
        new Thread(new Output(r)).start();
    }
}

上面再生产和消费都是单线程的情况下是没有问题的,但是如果变成了两个生产者和两个消费者,且该资源池只能存放一条数据,那么上面代码就需要修改了。

第一点:需要将上面代码的 notify() 改成 notifyAll()。因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。
第二点:需要将

if (flag)
            try {this.wait();} catch (Exception e) {}

改成:

while(flag)
            try {this.wait();} catch (Exception e) {}

原因:让被唤醒的线程再一次判断标记。

多线程版本的完整代码如下:

class ProducerConsumerDemo {
    public static void main(String[] args) {
        Resource r = new Resource();

        Producer pro = new Producer(r);
        Consumer con = new Consumer(r);

        new Thread(pro).start();
        new Thread(pro).start();
        new Thread(con).start();
        new Thread(con).start();

    }
}

class Resource {
    private String name;
    private int count = 1;
    private boolean flag = false;

    // t1 t2
    public synchronized void set(String name) {
        while (flag)
            try {this.wait();} catch (Exception e) {}// t1(放弃资格) t2(获取资格)
        this.name = name + "--" + count++;

        System.out.println(Thread.currentThread().getName() + "...生产者.." + this.name);
        flag = true;
        this.notifyAll();
    }

    // t3 t4
    public synchronized void out() {
        while (!flag)
            try {wait();} catch (Exception e) {}// t3(放弃资格) t4(放弃资格)
        System.out.println(Thread.currentThread().getName() + "...消费者........." + this.name);
        flag = false;
        this.notifyAll();
    }
}

class Producer implements Runnable {
    private Resource res;

    Producer(Resource res) {
        this.res = res;
    }

    public void run() {
        while (true) {
            res.set("+商品+");
        }
    }
}

class Consumer implements Runnable {
    private Resource res;

    Consumer(Resource res) {
        this.res = res;
    }

    public void run() {
        while (true) {
            res.out();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值