java线程之Condition、ReentrantLock

时间:2021-06-03 21:00:57

Condition是线程之间用来通信的,设计模式里的观察者模式。

例子,上课前,同学在玩,一个同学观察老师是不是来了,如果来了,叫其他同学坐好。

package com.concurrent;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import junit.framework.TestCase;

public class TestCondition extends TestCase {
	static final CountDownLatch cdl = new CountDownLatch(31);

	public void testCondition() {
		Monitor monitor = new Monitor();
		ExecutorService executorService = Executors.newFixedThreadPool(31);

		for (int i = 0; i < 30; i++) {
			Student student = new Student(monitor);
			monitor.addClassMate(student);
			executorService.execute(student);
		}
		executorService.execute(monitor);

		System.out.println(Thread.currentThread() + "老师还没来");
		monitor.setTeacherIsComing(true);
		System.out.println(Thread.currentThread() + "老师来了");

		try {
			cdl.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		executorService.shutdown();
	}

	static class Student implements Runnable {
		private Monitor monitor;

		Student() {

		}

		Student(Monitor monitor) {
			this.monitor = monitor;
		}

		@Override
		public void run() {

			try {
				monitor.getLock().lock();
				while (!monitor.isTeacherIsComing()) {
					monitor.getCondition().await();
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				monitor.getLock().unlock();
				cdl.countDown();
			}
			System.out.println(Thread.currentThread() + "回到自己座位,坐下");
		}
	}

	static class Monitor extends Student {
		private boolean teacherIsComing = false;

		private Set<Student> classMates = new HashSet<Student>();

		private Lock lock = new ReentrantLock();

		private Condition condition = lock.newCondition();

		@Override
		public void run() {
			lock.lock();
			while (!teacherIsComing) {
				System.out.println(Thread.currentThread() + "看老师是否来了");
			}
			condition.signalAll();
			lock.unlock();
			cdl.countDown();
		}

		public boolean isTeacherIsComing() {
			return teacherIsComing;
		}

		public void setTeacherIsComing(boolean teacherIsComing) {
			this.teacherIsComing = teacherIsComing;
		}

		public void addClassMate(Student student) {
			classMates.add(student);
		}

		public Condition getCondition() {
			return condition;
		}

		public Lock getLock() {
			return lock;
		}
	}
}

输出:

Thread[main,5,main]老师还没来
Thread[main,5,main]老师来了
Thread[pool-1-thread-1,5,main]回到自己座位,坐下
Thread[pool-1-thread-2,5,main]回到自己座位,坐下
Thread[pool-1-thread-3,5,main]回到自己座位,坐下
Thread[pool-1-thread-5,5,main]回到自己座位,坐下
Thread[pool-1-thread-7,5,main]回到自己座位,坐下
Thread[pool-1-thread-4,5,main]回到自己座位,坐下
Thread[pool-1-thread-6,5,main]回到自己座位,坐下
Thread[pool-1-thread-8,5,main]回到自己座位,坐下
Thread[pool-1-thread-10,5,main]回到自己座位,坐下
Thread[pool-1-thread-9,5,main]回到自己座位,坐下
Thread[pool-1-thread-11,5,main]回到自己座位,坐下
Thread[pool-1-thread-12,5,main]回到自己座位,坐下
Thread[pool-1-thread-13,5,main]回到自己座位,坐下
Thread[pool-1-thread-15,5,main]回到自己座位,坐下
Thread[pool-1-thread-14,5,main]回到自己座位,坐下
Thread[pool-1-thread-16,5,main]回到自己座位,坐下
Thread[pool-1-thread-18,5,main]回到自己座位,坐下
Thread[pool-1-thread-17,5,main]回到自己座位,坐下
Thread[pool-1-thread-20,5,main]回到自己座位,坐下
Thread[pool-1-thread-19,5,main]回到自己座位,坐下
Thread[pool-1-thread-21,5,main]回到自己座位,坐下
Thread[pool-1-thread-22,5,main]回到自己座位,坐下
Thread[pool-1-thread-23,5,main]回到自己座位,坐下
Thread[pool-1-thread-24,5,main]回到自己座位,坐下
Thread[pool-1-thread-25,5,main]回到自己座位,坐下
Thread[pool-1-thread-26,5,main]回到自己座位,坐下
Thread[pool-1-thread-27,5,main]回到自己座位,坐下
Thread[pool-1-thread-28,5,main]回到自己座位,坐下
Thread[pool-1-thread-29,5,main]回到自己座位,坐下
Thread[pool-1-thread-30,5,main]回到自己座位,坐下