天天看点

condition精准控制

Lock版的生产者消费者问题

那么在synchronized中呢,我们是使用wait和notify来控制线程的。

public synchronized void increment() throws InterruptedException {
       while (number != 0) {
            // 等待
            this.wait();100);
        number++; // 业务
        System.out.println(Thread.currentThread().getName() + " => " + number);
        // 通知其它线程我+1加完了
        this.notifyAll();      

用了Lock之后、会有一些细微的改变,wait->condition.await, notify->condition.signal

class doSomething {

    private int number = 0;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    // +1
    public void increse() throws InterruptedException {
        lock.lock();
        try {

            while (number != 0) {
                condition.await();100);
            number++;
            System.out.println(Thread.currentThread().getName() + "->" +condition.signalAll();catch (Exception e) {
            e.printStackTrace();
        } finally {

            lock.unlock();
        }

    }


    // -1
    public void decrese() throws InterruptedException {

        lock.lock();
        try {
            while (number == 0) {
                condition.await();100);
            number--;
            System.out.println(Thread.currentThread().getName() + "->" + number);
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }

}      

思考:既然有了wait和notify、那为什么我们还要多此一举来使用condition的等待和唤醒呢?

  这是因为condition能够做到有序,精准的通知和唤醒线程

那么如何做到有序精准的来唤醒线程呢?

public class C {
    public static void main(String[] args) {
        doSomething2 doSomething2 = new doSomething2();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                doSomething2.printA();

            }
        }, "A").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                doSomething2.printB();

            }

        }, "B").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                doSomething2.printC();

            }

        }, "C").start();

    }
}

@SuppressWarnings("all")
class doSomething2 {

    private int number = 1;
    Lock lock = new ReentrantLock();
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();

    public void printA() {
        lock.lock();
        try {
            while (number != 1) {
                // 等待
                condition1.await();
            }
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + "AAA");
            // 唤醒
            condition2.signal();catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printB() {
        lock.lock();
        try {
            while (number != 1) {
                // 等待
                condition2.await();
            }
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + "BBB");
            // 唤醒
            condition3.signal();catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void printC() {
        lock.lock();
        try {
            while (number != 1) {
                // 等待
                condition3.await();
            }
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + "CCC");
            // 唤醒
            condition1.signal();catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}