1.如何得到Condition
在Lock中
Condition |
newCondition()
返回绑定到此 Lock 实例的新
Condition 实例。 |
2.使用Condition进行线程之间的通信 改进传统的线程之间同信代码
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 子线程循环10次 主线程循环100次 如此交替 50次
*
* @author hao.su
*
*/
public class ConditionCommunication {
public static void main(String[] args) {
final Business business = new Business();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 50; i++) {
business.sub(i);
}
}
}).start();
for (int i = 0; i < 50; i++) {
business.main(i);
}
}
static class Business {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
boolean bShouldSub = true;
public void sub(int i) {
lock.lock();
try {
while (!bShouldSub) {// 用while防止未唤醒
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int j = 0; j < 10; j++) {
System.out.println("sub thread sequence of" + j
+ ",loop of" + i);
}
} catch (Exception e) {
}finally{
lock.unlock();
}
}
public void main(int i) {
lock.lock();
try {
while (bShouldSub) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int j = 0; j < 100; j++) {
System.out.println("main thread sequence of" + j
+ ",loop of" + i);
}
bShouldSub = true;
condition.signal();
} catch (Exception e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}
}
}
在等待Condition时,允许发生虚假唤醒,这通常作为基础平台语义的让步,对于大多数应用程序,这带来的实际影响很小,因为Condition总应该在一个循环中等待,并测试正被等待的状态声明,某个实现可以随意移除可能的虚假唤醒,但建议应用程序程序员总是假定这些虚假唤醒可能发生,因此总是在一个循环中等待。Condition
实例实质上被绑定到一个锁上。要为特定
Lock
实例获得 Condition
实例,请使用其
newCondition()
方法。
作为一个示例,假定有一个绑定的缓冲区,它支持 put
和 take
方法。如果试图在空的缓冲区上执行
take
操作,则在某一个项变得可用之前,线程将一直阻塞;如果试图在满的缓冲区上执行 put
操作,则在有空间变得可用之前,线程将一直阻塞。我们喜欢在单独的等待 set 中保存put
线程和
take
线程,这样就可以在缓冲区中的项或空间变得可用时利用最佳规划,一次只通知一个线程。可以使用两个Condition
实例来做到这一点。
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
但是ArrayBlockingQueue类提供了这项功能,因此没有必要去实现该项功能
4.实现功能,当A执行完毕后执行B之后执行C c执行之后执行A 如此循环
package com.qunar.thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 子线程循环10次 主线程循环100次 如此交替 50次
*
* @author hao.su
*
*/
public class ThreeConditionCommunication {
public static void main(String[] args) {
final Business business = new Business();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 50; i++) {
business.sub2(i);
}
}
}).start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 50; i++) {
business.sub3(i);
}
}
}).start();
for (int i = 0; i < 50; i++) {
business.main(i);
}
}
static class Business {
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
int iShouldSub = 1;
public void sub2(int i) {
lock.lock();
try {
while (iShouldSub != 2) {// 用while防止未唤醒
try {
condition2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int j = 0; j < 10; j++) {
System.out.println("sub2 thread sequence of" + j
+ ",loop of" + i);
}
iShouldSub = 3;
condition3.signal();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
public void sub3(int i) {
lock.lock();
try {
while (iShouldSub!=3) {// 用while防止未唤醒
try {
condition3.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int j = 0; j < 10; j++) {
System.out.println("sub3 thread sequence of" + j
+ ",loop of" + i);
}
iShouldSub = 1;
condition1.signal();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
public void main(int i) {
lock.lock();
try {
while (iShouldSub!=1) {
try {
condition1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int j = 0; j < 100; j++) {
System.out.println("main thread sequence of" + j
+ ",loop of" + i);
}
iShouldSub = 2;
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}