在之前的学习中,无论是通过synchronized建立同步代码块,还是通过synchronized建立同步函数,都是把对象看成一把锁来实现同步,这种解释有点牵强,而且在消费者—生产者的那个实例中,其实还有个问题,那就是在避免线程全部冻结时,没必要把相同功能的线程解冻,只要把其他功能的线程解冻即可,也就是说消费者线程只要解冻生产者线程即可,没必要把其他消费者线程也解冻,为了解决这些问题,java1.5版本推出了同步的升级办法,那就是通过Lock对象和Condition对象实现同步。
新的同步办法不再需要synchronized关键字,而引入了更加形象的Lock。
Lock实质上是是一个接口,在创建对象时,使用Lock的子类ReentrantLock来建立对象。
使用方法:建立对象后,在需要同步的代码前一行写 Lock对象.lock(); ,在同步代码后一行写 Lock对象.unlock();
Lock对象用来控制线程的进出,而对线程的操作则由Condition对象来操作;
对应关系:
wait——await(两者均抛出异常)
notify——signal
notifyAll——signalAll
Condition同样是接口,建立方法(比较神奇) Condition 对象名=Lock对象.newCondition();
API上的解释:Condition
实例实质上被绑定到一个锁上。要为特定 Lock
实例获得 Condition
实例,请使用其 newCondition()
方法。
Condition对象的优势在于,signal只能唤醒被相同Condition对象的await方法冻结的线程,因此,可以建立多个Condition对象,分别用来冻结和解冻不同功能的线程
最后要注意的是,Lock接口属于类包java.util.concurrent.locks,因此,在写代码前,应该先导入类包
上次实例的升级版:
//需求:产品每生产一个消费一个
import java.util.concurrent.locks.*;
class ProducerConsumerDemo
{
public static void main(String[] args)
{
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
Lock lock=new ReentrantLock();
Condition pro = lock.newCondition();
Condition con = lock.newCondition();
public void set(String name)
{
lock.lock();
while(flag)
try{pro.await();}catch(Exception e){}
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
con.signalAll();
lock.unlock();
}
public void out()
{
lock.lock();
while(!flag)
try{con.await();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
flag = false;
pro.signalAll();
lock.unlock();
}
}
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
res.set("+商品+");
}
}
}
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
res.out();
}
}
}
注意看Resource类的变化