Java基础14--多线程(四)

2014-11-24 07:36:58 · 作者: · 浏览: 4
id main(String[] args) { Resource r = new Resource(); Producer pro = new Producer(r); Consumer con = new Consumer(r); Thread t0 = new Thread(pro); Thread t1 = new Thread(pro); Thread t2 = new Thread(con); Thread t3 = new Thread(con); t0.start(); t1.start(); t2.start(); t3.start(); } }

说明:

if和notify的情况:

to拿到执行权,if(flag)为假,生产烤鸭1,count为2,置flag为true,notify一次,若t0继续拿执行权,if(flag)为true,被wait,t1执行,if(flag)为true,被wait,t2执行,if(!flag)为假,消费了烤鸭1,置flag为false,唤醒t0,t1中的一个,假设t0被唤醒,t3执行,if(!flag)为true,被wait(),t2执行,if(!flag)为true,也被wait(),这时活着的线程只有t0,t0执行,此时不再判断if,生产了烤鸭2,count为3,flag为true,notify随机唤醒一个,若唤醒了t1,t1也不判断if,生产了烤鸭3,若唤醒t2,t2消费了烤鸭3,这时烤鸭2未被消费,此时烤鸭2没有消费者,就出现了生产出的烤鸭无人消费的问题。

结果打印如:

生产烤鸭1

...消费烤鸭1

生产烤鸭2 //烤鸭2没有被消费

生产烤鸭3

...消费烤鸭3

while和notify的情况:

继续上面的说法,此时t1,t2,t3被wait,只有t0活着,flag为false,t0被唤醒后,需要判断while(flag),为假,生产烤鸭4,置flag为true,t0唤醒t1,t0继续执行,while(flag)为true,t0被wait,t1被唤醒后也判断while(flag)为true,被wait,这时4个线程都被wait了,造成死锁。

While和notifyAll解决了问题,但效率降低了,为此,JDK1.5提供了解决方案。

14-5,多生产者多消费者问题-JDK1.5性特性-Lock

同步代码块对于锁的操作时隐式的。

JDK1.5以后将同步和锁封装成了对象,并将操作锁的隐式方式定义到了该对象中,将隐式动作变成了显示动作。

Lock接口在java.util.concurrent.locks包中,用Lock需要导入java.util.concurrent.locks.*;

标准写法:

//Lock是接口,ReentrantLock是Lock的子类,实现了Lock
Lock lock = new ReentrantLock();
public void show() {
	lock.lock();
	try {
		//代码中可能会抛出异常,用try处理,抛出异常后会导致程序跳转,这样就不能释放锁了
		//释放锁是必须执行的,所以放在finally内。
		code...
	}finally {
		//释放锁
		lock.unlock();
	}
}

14-6,JDK1.5新特性-Condition

1,Lock接口:替代了同步代码或者同步函数,将同步的隐式锁操作变成显示所操作,同时更为灵活,可以在一个锁上加多组监视器。

lock()方法获取锁。

unlock()方法释放锁,通常定义在finally代码块中。

2,Condition接口:替代了Object中的wait(),notify(),notifyAll()方法,将这些监视器方法单独进行了封装,变成Condition监视器对象,可以与任意锁进行组合。

await():-->wait();

signal();-->notify();

signalAll();-->notifyAll();

3,实现机制对比:

旧方法:

class Object {

wait();

notify();

notifyAll();

}

class Demo extends Object {}

...

Demo d = new Demo();

synchronized(d){

d.wait();

}

一个锁只能实现一组wait,notify,notifyAll方法。

JDK1.5新特性:

interface Condition {

await();

signal();

signalAll();

}

Lock lock = new ReentrantLock();

Condition c1 = lock.newCondition();

Condition c2 = lock.newCondition();

可以创建多个Condition对象,实现多组Condition中的await,signal,signalAll。

4,14-4中的代码可以写为:

//创建一个锁对象
Lock lock = new ReentrantLock();
//通过已有的锁获取该锁上的监视器对象
Condition con = lock.newCondition();
public voidset(String name) {
	//获取锁
	lock.lock();
	try {
		while(true) {
			try {
				//调用监视器的await方法
				con.awati();
			}catch(InterrputedException e) {}
		}
		this.name = name + count;
		count++;
		System.out.println(Thread.currentThread().getName()+"生产者5.0"+this.name);
		flag = true;
		//调用监视器的signalAll方法
		con.signalAll();
	} finally {
		//释放锁
		lock.unlock();
	}
}

14-7,解决方案

1,在14-4的程序中的Resource类改为。

import java.util.concurrent.locks.*;
class Resource {
	private String name;
	private int count = 1;
	private boolean flag = false;
	//创建锁对象
	Lock lock = new ReentrantLock();
	//通过已经有的锁获取两组监视器,一组监视生产者,一组监视消费者
	Condition producer_con = lock.newCondition();
	Condition consumer_con = lock.newCondition();
	public void set(String name) {
		lock.lock();
		try {
			while(true) {
				try {
					producer_con.await();
				}catch(InterruputedException e) {}
			}
			this.name = na