java线程学习(七):JDK并发包之Condition条件

在上一篇中,我们学习了JDK并发包的重入锁的使用,然而线程流程的处理,并不单单是上锁,中断的操作,还有之前学到过的等待wait(),通知notify()等等,但wait(),notify()是与synchronized()搭配使用的。对应于jdk并发包,我们也有相应的类去使用,那就是重入锁的好搭档——Condition接口。

Condition接口有以下方法:

public interface Condition {
	void await() throws InterruptedException;
	void awaitUninterruptibly();
	long awaitNanos(long var1) throws InterruptedException;
	boolean await(long var1, TimeUnit var3) throws InterruptedException;
	boolean awaitUntil(Date var1) throws InterruptedException;
	void signal();
	void signalAll();
}

Condition的特性:

  • Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signalAll()相当于Object的notifyAll()方法。不同的是,Object中的这些方法是和同步锁捆绑使用的;而Condition是需要与互斥锁/共享锁捆绑使用的。
  • Condition它更强大的地方在于:能够更加精细的控制多线程的休眠与唤醒。对于同一个锁,我们可以创建多个Condition,在不同的情况下使用不同的Condition。
    例如,假如多线程读/写同一个缓冲区:当向缓冲区中写入数据之后,唤醒"读线程";当从缓冲区读出数据之后,唤醒"写线程";并且当缓冲区满的时候,"写线程"需要等待;当缓冲区为空时,"读线程"需要等待。
  • 如果采用Object类中的wait(), notify(), notifyAll()实现该缓冲区,当向缓冲区写入数据之后需要唤醒"读线程"时,不可能通过notify()或notifyAll()明确的指定唤醒"读线程",而只能通过notifyAll唤醒所有线程(但是notifyAll无法区分唤醒的线程是读线程,还是写线程)。 但是,通过Condition,就能明确的指定唤醒读线程。

注:建议查看之前的文章去了解下wait和notify的使用,后续对Condition的使用是很有帮助的。

Condition的使用(Condition是需要配合重入锁使用的)
举个例子:

package stop_demo;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 例子说明:
 * add()方法:当集合长度为10时,就挂起当前的线程, 让其他线程先走。否则就会添加一条信息,然后唤起执行sub()的线程
 * sub()方法:当长度为0时,同理操作
 * 
 * @author fei
 *
 */
public class Condition_demo implements Runnable {

	private final static Lock lock = new ReentrantLock();

	private final static Condition addCondition = lock.newCondition();

	private final static Condition subCondition = lock.newCondition();


	private static int num = 0;
	private static List<String> lists = new LinkedList<String>();
	private boolean flag;

	public Condition_demo(boolean flag){
		this.flag=flag;

	}

	@Override
	public void run() {
		if (flag) {
			add();//执行线程添加器
		}
		else {
			sub();//执行线程减数器
		}

	}

	public void add() {
		lock.lock();

		try {
			while(lists.size() == 10) {//当集合已满,则"添加"线程等待
				addCondition.await();//满了就挂起来
			}

			num++;
			lists.add("add Banana" + num);
			System.out.println("处于‘增加’线程方法  集合长度为:   " + lists.size());
			System.out.println("The Current Thread is " + Thread.currentThread().getName());
			System.out.println("==============================");
			this.subCondition.signal();//唤起“减少”线程

		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {//释放锁
			lock.unlock();
		}
	}


	public void sub() {
		lock.lock();
		try {
		
			while(lists.size() == 0) {//当集合为空时,"减少"线程等待
				System.out.println("‘减少’线程已挂起~~~~");
				subCondition.await();
			}
			String str = lists.get(0);
			lists.remove(0);
			System.out.println("处于‘减少’线程方法:  集合内容为:  [" + str + "]");
			System.out.println("The Current Thread is " + Thread.currentThread().getName());
			System.out.println("==============================");
			num--;
			addCondition.signal();//唤起“增加”线程

		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

	public static void main(String[] args) throws InterruptedException {
		Condition_demo task1 = new Condition_demo(true);
		Condition_demo task2 = new Condition_demo(false);

		Thread t1 = new Thread(task1);
		Thread t2 = new Thread(task1);
		Thread t3 = new Thread(task1);
		Thread t4 = new Thread(task1);
		Thread t5 = new Thread(task1);
		Thread t7 = new Thread(task2);
		Thread t6 = new Thread(task2);
		Thread t8 = new Thread(task2);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
		t6.start();
		t7.start();
		t8.start();

	}
}

可以复制当前例子到demo中,执行后就会发现,condition和lock真是个好搭档!!

猜你喜欢

转载自blog.csdn.net/shenhaiyushitiaoyu/article/details/85099868