多线程Condition用法

深知身在情长在,怅望江头江水声
此前,我们知道用synchronized与wait()和notify()/notifyAll()方法结合可以实现等待/通知模式。但是,在使用notify()/notifyAll()方法进行通知时,被通知的线程却是由JVM随机选择的。为了摆脱这种窘境,Java在1.5引入了ReentrantLock和Condition类结合使用来达到有选择性的进行线程通知,在调度线程上更加灵活。下面是个测试方法:


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


public class Test {
    private Lock lock = new ReentrantLock();
    public Condition condition = lock.newCondition();
    //等待
    public void await() {
        try {
            lock.lock();    //调用lock.lock()方法的线程就持有了"对象监视器",其他线程只有等待锁被释放时再次争抢
            System.out.println("await()时间为:" + System.currentTimeMillis());
            condition.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
     }
     //通知
     public void signal() {
        try {
            lock.lock();
            System.out.println("signal()时间为:" + System.currentTimeMillis());
            condition.signal();
        } finally {
            lock.unlock();
        }
     }
}

//线程类
class ThreadA extends Thread {
    private Test test;
    public ThreadA(Test test) {
        super();
        this.test = test;
    }
    @Override
    public void run() {
        test.await();
    }
}

//运行主类
class Run {
    public static void main(String[] args) throws InterruptedException {
        Test test = new Test();
        ThreadA a = new ThreadA(test);
        a.start();
        Thread.sleep(3000);
        test.signal();
    }
}

运行结果如下:
这里写图片描述
如图,成功的实现了等待/通知模式
Object类中的wait()方法相当于Condition类中await()方法。
Object类中的wait(long time)方法相当于Condition类中await(long time,TimeUnit unit)方法。
Object类中的notify()方法相当于Condition类中signal()方法。
Object类中的notifyAll()方法相当于Condition类中signalAll()方法。

修改上面代码,测试实现部分通知:


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


public class Test {
    private Lock lock = new ReentrantLock();
    public Condition conditionB = lock.newCondition();
    public Condition conditionA = lock.newCondition();
    //等待
    public void awaitA() {
        try {
            lock.lock();    //调用lock.lock()方法的线程就持有了"对象监视器",其他线程只有等待锁被释放时再次争抢
            System.out.println("awaitA()时间为:" + System.currentTimeMillis());
            conditionA.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
     }
     //等待
    public void awaitB() {
        try {
            lock.lock();    //调用lock.lock()方法的线程就持有了"对象监视器",其他线程只有等待锁被释放时再次争抢
            System.out.println("awaitB()时间为:" + System.currentTimeMillis());
            conditionB.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
     }
     //通知
     public void signalA() {
        try {
            lock.lock();
            System.out.println("signalA()时间为:" + System.currentTimeMillis());
            conditionA.signalAll();
        } finally {
            lock.unlock();
        }
     }
     //通知
     public void signalB() {
        try {
            lock.lock();
            System.out.println("signalB()时间为:" + System.currentTimeMillis());
            conditionB.signalAll();
        } finally {
            lock.unlock();
        }
     }
}

//线程类
class ThreadA extends Thread {
    private Test test;
    public ThreadA(Test test) {
        super();
        this.test = test;
    }
    @Override
    public void run() {
        test.awaitA();
    }
}

//线程类
class ThreadB extends Thread {
    private Test test;
    public ThreadB(Test test) {
        super();
        this.test = test;
    }
    @Override
    public void run() {
        test.awaitB();
    }
}

//运行主类
class Run {
    public static void main(String[] args) throws InterruptedException {
        Test test = new Test();
        ThreadA a = new ThreadA(test);
        a.start();
        ThreadB b = new ThreadB(test);
        b.start();
        Thread.sleep(3000);
        test.signalA(); //唤醒A
    }
}

实验结果:
这里写图片描述
由图可以看出,只有A被唤醒了。所以实现了部分唤醒的功能。

通过此实验可以得知,使用ReentrantLock对象可以唤醒指定种类的线程,这是控制部分线程行为的方便方式。

猜你喜欢

转载自blog.csdn.net/a_runner/article/details/80640675