标签:style java 使用 os io strong for ar
分享JUC中的Condition的比较少见,我见了大部分文章都是讲其中的一个例子BoundedBuffer。今天先从Condition接口的几个方法说起,然后在把BoundedBuffer搞死锁了。来看看Condition在使用的时候需要注意什么。
上源代码:(字数限时,原谅我把注释都去掉了)
public interface Condition {
void await() throws InterruptedException;
void awaitUninterruptibly();
long awaitNanos(long nanosTimeout) throws InterruptedException;
boolean await(long time, TimeUnit unit) throws InterruptedException;
boolean awaitUntil(Date deadline) throws InterruptedException;
void signal();
void signalAll();
}
Condtion接口主要是用来描述一个锁的几个状态。具体创建方法如下
Condition notFull = lock.newCondition();
其实Condition的功能有点类似Object当中的wait和notify方法。但是稍做了加强。提供了多种wait的策略。另外用Condition的最大好处就是,一个锁是可以拥有多个状态的。如果用Object的wait和notify只能有一个。
具体看一下以下几个wait方法:
void await() throws InterruptedException; void awaitUninterruptibly(); long awaitNanos(long nanosTimeout) throws InterruptedException; boolean await(long time, TimeUnit unit) throws InterruptedException; boolean awaitUntil(Date deadline) throws InterruptedException;
await()
解读:会将当前线程设置成等待状态,一直到有signal方法的触发或者Interrupt的发生才会恢复状态。当然interrupt了就直接抛异常了,不会继续往下走
异常:InterruptedException
awaitUninterruptibly()
解读:会将当前线程设置成等待状态,一直到有signal方法的触发。不会被Interrupt阻断。
long awaitNanos(long nanosTimeout)
参数:最大的等待的时间
返回:实际的剩余时间的估算(nanosTimeout - 实际等待时间)正值可以用于后续的继续等待,例如延迟加载这样的场景,可以让程序继续等待剩下的时间,完成计时。如果为0或者负数时,表示没有剩余时间了。
解读:会将当前线程设置成等待状态一直到设定的最大等待时间。当遇到singal或者Interrupt时才会恢复。
异常:InterruptedException
boolean await(long time, TimeUnit unit) 和 boolean awaitUntil(Date deadline)
参数:具体时间一个是间断的时间,另一个是具体的时刻。但实质是一样的。
解读:具体等待一段时间或一个到一个时间点。如果遇到singal则返回True,否则返回false.
异常:InterruptedException
void signal(); void signalAll();
void signal()
解读:唤醒一个等待的线程,如果所有的线程都在等待此条件,则选择其中的一个唤醒。在从 await 返回之前,该线程必须重新获取锁。
void signalAll()
解读:唤醒所有线程,如果所有的线程都在等待此条件,则选择其中的一个唤醒。在从 await 返回之前,该线程必须重新获取锁。
public class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[2];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
String threadName = Thread.currentThread().getName();
System.out.println(threadName+" is waiting for lock");
lock.lock();
System.out.println(threadName+" got lock");
try {
while (count == items.length){
System.out.println(threadName+" is waiting for notFull condition");
notFull.await();
System.out.println(threadName+" left notFull condition");
}
items[putptr] = x;
if (++putptr == items.length){
putptr = 0;
}
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
String threadName = Thread.currentThread().getName();
System.out.println(threadName+" is waiting for lock");
lock.lock();
System.out.println(threadName+" got lock");
try {
while (count == 0){
System.out.println(threadName+" is waiting for notEmpty condition");
notEmpty.await();
System.out.println(threadName+" left notEmpty condition");
}
Object x = items[takeptr];
if (++takeptr == items.length){
takeptr = 0;
}
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
问得最多的一个问题:这里的await有必要吗?
while (count == 0){
System.out.println(threadName+" is waiting for notEmpty condition");
notEmpty.await();
System.out.println(threadName+" left notEmpty condition");
}
回答:有必要,当count等于0的时候.如果没有await释放锁,那么其他线程会认为lock一直被占有,将无法获得锁。
为了验证这一点,写了一个测试方法:
public class PutTask implements Runnable {
BoundedBuffer bb = new BoundedBuffer();
int count = 0;
public PutTask(BoundedBuffer bb){
this.bb = bb;
this.count = 0;
}
@Override
public void run() {
try {
String threadName = Thread.currentThread().getName();
bb.put(count);
System.out.println(threadName+" put "+count);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class TakeTask implements Runnable {
BoundedBuffer bb = new BoundedBuffer();
public TakeTask(BoundedBuffer bb){
this.bb = bb;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+" take "+bb.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ConditionTest {
public static void main(String[] args) throws InterruptedException{
BoundedBuffer bb = new BoundedBuffer();
PutTask putTask = new PutTask(bb);
TakeTask takeTask1 = new TakeTask(bb);
TakeTask takeTask2 = new TakeTask(bb);
final ScheduledExecutorService service = Executors.newScheduledThreadPool(3);
//service.scheduleAtFixedRate(putTask, 0, 1, TimeUnit.SECONDS);
service.scheduleAtFixedRate(takeTask1, 0, 1, TimeUnit.SECONDS);
service.scheduleAtFixedRate(takeTask2, 0, 1, TimeUnit.SECONDS);
Thread.currentThread().sleep(3000l);
Thread t = new Thread(putTask);
t.start();
}
}
将notEmpty.await()注释掉,执行的结果为
pool-1-thread-2 is waiting for lock
pool-1-thread-2 got lock
pool-1-thread-1 is waiting for lock
Thread-0 is waiting for lock
可以看到除了pool-1-thread-2获得了锁,其他线程都在等待锁。但这个时候pool-1-thread-2被while(count==0)锁死,无法跳出。程序进入死锁。
恢复notEmpty.await()的注释,执行的结果为
pool-1-thread-2 is waiting for lock
pool-1-thread-2 got lock
pool-1-thread-2 is waiting for notEmpty condition
pool-1-thread-1 is waiting for lock
pool-1-thread-1 got lock
pool-1-thread-1 is waiting for notEmpty condition
Thread-0 is waiting for lock
Thread-0 got lock
Thread-0 put 0
pool-1-thread-2 left notEmpty condition
pool-1-thread-2 take 0
pool-1-thread-2 is waiting for lock
pool-1-thread-2 got lock
pool-1-thread-2 is waiting for notEmpty condition
j.u.c.locks.condition,布布扣,bubuko.com
标签:style java 使用 os io strong for ar
原文地址:http://my.oschina.net/readjava/blog/304040