1. 程式人生 > >Java多執行緒學習筆記(五) 使用Condition實現等待/通知

Java多執行緒學習筆記(五) 使用Condition實現等待/通知

使用Condition實現等待/通知

1. 使用Condition

在使用notify()/notifyAll()方法進行通知時,被通知的執行緒是由JVM隨機選擇的。但使用ReentrantLock類結合Condition類可以實現“選擇性通知”,這個功能是相當重要的。

1.1 MyService

public class MyService {

    private Lock lock = new ReentrantLock();
    public Condition condition = lock.newCondition();

    public void await(){
        try{
            lock.lock();
            System.out.println("await time is " + System.currentTimeMillis());
            condition.
await(); }catch (InterruptedException e){ e.printStackTrace(); }finally { lock.unlock(); } } public void signal(){ try{ lock.lock(); System.out.println("signal time is " + System.currentTimeMillis()); condition.
signal(); }finally { lock.unlock(); } } }

1.2 ThreadA

public class ThreadA extends Thread {
    private MyService service;

    public ThreadA(MyService service){
        super();
        this.service = service;
    }

    @Override
    public void run(){
        service.await();
    }
}

1.3 Test

public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyService service = new MyService();
        ThreadA a = new ThreadA(service);
        a.start();

        Thread.sleep(3000);
        service.signal();
    }
}

1.4 執行結果

await time is 1541569098094
signal time is 1541569101095

1.5 方法對比

Object類 Condition類
wait() await()
wait(long timeout) await(long time, TimeUnit unit)
notify() signal()
notifyAll() signalAll()

2. 使用多個Condition實現通知部分執行緒

2.1 MyService

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyService {
    private Lock lock = new ReentrantLock();
    public Condition conditionA = lock.newCondition();
    public Condition conditionB = lock.newCondition();

    //region await
    public void awaitA(){
        try{
            lock.lock();
            System.out.println("begin awaitA");
            conditionA.await();
            System.out.println("end awaitA");
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void awaitB(){
        try{
            lock.lock();
            System.out.println("begin awaitB");
            conditionB.await();
            System.out.println("end awaitB");
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    //endregion

    //region signalAll
    public void signalAll_A(){
        try{
            lock.lock();
            System.out.println("signalAll_A");
            conditionA.signalAll();
        }finally {
            lock.unlock();
        }
    }

    public void signalAll_B(){
        try{
            lock.lock();
            System.out.println("signalAll_B");
            conditionB.signalAll();
        }finally {
            lock.unlock();
        }
    }
    //endregion
}

2.2 ThreadA

public class ThreadA extends Thread {
    private MyService service;

    public ThreadA(MyService service){
        super();
        this.service = service;
    }

    @Override
    public void run(){
        service.awaitA();
    }
}

2.3 ThreadB

public class ThreadB extends Thread {
    private MyService service;

    public ThreadB(MyService service){
        super();
        this.service = service;
    }

    @Override
    public void run(){
        service.awaitB();
    }
}

2.4 Test

public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyService service = new MyService();

        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();

        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();

        Thread.sleep(3000);
        service.signalAll_A();
    }
}

2.5 執行結果

begin awaitA
begin awaitB
signalAll_A
end awaitA