从JDK1.5 之后,提供新的等待唤醒机制Lock
之前用的wait(),notify(),notifyAll(),都是在JDK1.5之前使用,
不同的线程在锁住同一个对象后,调用wait()线程等待,notifyAll()唤醒所有的线程池里的线程,但是通常我们不需要唤醒所有的线程,只唤醒我们需要的线程即可,JDK1.5后提供Lock 接口。
上一个列子,做了下修改。
new ReentrantLock(); 是实现Lock 接口。
Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,也是就说再同一个锁下面可以创建N 个对象,每个对象都有独立的(wait、notify 和 notifyAll)方法,而之前的synchronized (r) 只用一个(wait、notify 和 notifyAll)方法。
在Condition中,用await()替换wait(),用signal()替换notify(),用signalAll()替换notifyAll(),传统线程的通信方式,Condition都可以实现,这里注意,Condition是被绑定到Lock上的,要创建一个Lock的Condition必须用newCondition()方法。
所以condition 是更高效的线程通信方式
package util;
public class Input implements Runnable{
private Resource1 r;
public Input(Resource1 r){
this.r = r;
}
public void run() {
int x = 0;
while(true){
if(x == 0){
r.set("mike", "man");
}else{
r.set("林心如", "女");
}
x = (x+1)%2;
}
}
}
package util;
public class Output implements Runnable{
private Resource1 r;
public Output(Resource1 r){
this.r = r;
}
public void run() {
while(true){
r.out();
}
}
}
package util;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Resource1 {
public static Resource1 r = null;
private String name;
private String sex;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition_set = lock.newCondition();
private Condition condition_out = lock.newCondition();
public void set(String name,String sex){
lock.lock();
try {
while(flag){
condition_set.await();
}this.name = name;
this.sex = sex;
System.out.println("生产"+Thread.currentThread().getName()+ r.name+"-----"+r.sex);
flag = true;
condition_out.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void out(){
lock.lock();
try {
while(!flag){
condition_out.await();
}
System.out.println("消费"+Thread.currentThread().getName()+ r.name+"-----"+r.sex);
flag = false;
condition_set.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}
public static Resource1 getResource(){
if(r == null){
synchronized (Resource1.class) {
if(r == null){
r = new Resource1();
}
}
}
return r;
}
}
package util;
public class InputOuputDemo {
public static void main(String[] args) {
Input i = new Input(Resource1.getResource());
Output o = new Output(Resource1.getResource());
Thread t1 = new Thread(i);
Thread t2 = new Thread(o);
Thread t3 = new Thread(i);
Thread t4 = new Thread(o);
Thread t5 = new Thread(i);
Thread t6 = new Thread(o);
Thread t7 = new Thread(i);
Thread t8 = new Thread(o);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
t8.start();
}
}