首先先介绍下我们使用的两个1.5并发库的对象:
Lock和Condition:前者是对synchronized的替代,condition是对锁对象的替代,他可以实现一个Lock对应多个Condition;
这个改进使得线程间的通信更加安全可靠,解决了线程都在等待和唤醒所有线程的问题;
请看一个三个线程交替执行的例子;
package cn.itcast.concurrent;
public class ThreeThreadcommunicati {
public static void main(String[] args) {
final Business business = new Business();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
business.subA(i);
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
business.subB(i);
}
}
}).start();
for (int i = 0; i < 50; i++) {
business.main(i);
}
}
}
package cn.itcast.concurrent;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Business {
private Lock lock = new ReentrantLock();
private int flag = 1;
private Condition main_condition = lock.newCondition();
private Condition a_condition = lock.newCondition();
private Condition b_condition = lock.newCondition();
public void main(int i) {
lock.lock();
try {
while (flag != 1) {
main_condition.await();
}
for (int j = 0; j < 20; j++) {
System.out.println(Thread.currentThread().getName()
+ "main loop" + j + "of" + i);
}
flag=2;
a_condition.signal();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void subA(int i) {
lock.lock();
try{
while(flag!=2){
a_condition.await();
}
for (int j = 0; j < 20; j++) {
System.out.println(Thread.currentThread().getName()
+ "A loop" + j + "of" + i);
}
flag=3;
b_condition.signal();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void subB(int i) {
lock.lock();
try{
while(flag!=3){
b_condition.await();
}
for (int j = 0; j < 20; j++) {
System.out.println(Thread.currentThread().getName()
+ "B loop" + j + "of" + i);
}
flag=1;
main_condition.signal();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
lock.unlock();
}
}
}
需要注意的是:
1 :对于 记的判断和改变,灵活的使用int型变量;
2 :等待唤醒的对象不能搞混淆;
3 :释放锁的动作一定要执行, 此要放在finally块中;
4:将启动线程的操作和线程执行的代 分开存放,更 的面向对象,符合高类聚思想;
5:判断 记的用的是while而不是if,防止假唤醒的出现;即循环判断 记;
转发至微博
转发至微博