问题
自己编的的一个小题目:有两个线程,一个会不断的向一个共享变量上边添加字符A,另一个会不断的添加字符+,要求共享变量最后达到 "A+A+A+A+..."这样的形式。
不考虑线程同步和协调会怎么样
我们启两个线程,分别不断的向一个volatile变量追加A和+,然后每隔一段时间打印出这个变量观察。
代码:
private volatile static String kp = "";
public static void main(String[] args) {
Thread tA = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
kp = kp + "A";
try {
TimeUnit.SECONDS.sleep(1); //不会释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread tB = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
kp = kp + "+";
try {
TimeUnit.SECONDS.sleep(1); //不会释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
tA.start();
tB.start();
while(true) {
System.out.println(kp);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
A+
A++
A++AA
A++A+
A++A++A
A++A++A+A
A++A++A+A
A++A++A+AA
A++A++A+AA++
A++A++A+AA++
A++A++A+AA+++A
A++A++A+AA+++A+
A++A++A+AA+++A++
A++A++A+AA+++A++A
A++A++A+AA+++A++AA
A++A++A+AA+++A++AA+
A++A++A+AA+++A++AA+A
A++A++A+AA+++A++AA+AA
A++A++A+AA+++A++AA+AA+A
A++A++A+AA+++A++AA+AA+A+A
显然不满足题目的要求。
解决问题
要解决的问题其实是:协调多个线程按指定的交替顺序向共享变量追加相应的字符。
思路,设置一个ReentrantLock上两个Condition,A,B两个线程分别对应ConditionA和ConditionB,比如Thread A做完自己的操作,就会通过ConditionA.singal()通知其他线程,然后通过ConditionB.await()表明自己阻塞等待ConditionB也就是Thread B的操作。
完整代码:
public class ConditionTest {
private volatile static String kp = "";
private static ReentrantLock lock = new ReentrantLock(false);
private static Condition conditionA = lock.newCondition();
private static Condition conditionB = lock.newCondition();
public static void main(String[] args) {
Thread tA = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
try {
lock.lock();
kp = kp + "A";
TimeUnit.MILLISECONDS.sleep(200);; //不会释放锁
conditionA.signal(); //通知tB自己的操作做完了
conditionB.await(); //自己等待Conditon B也就是tB的操作
} catch (Exception e) {
e.printStackTrace();
}finally {
if(lock.isHeldByCurrentThread())
lock.unlock();
}
}
}
});
Thread tB = new Thread(new Runnable() {
@Override
public void run() {
while(true) {
try {
lock.lock();
kp = kp + "+";
TimeUnit.MILLISECONDS.sleep(500); //不会释放锁
conditionB.signal();
conditionA.await();
} catch (Exception e) {
e.printStackTrace();
}finally {
if(lock.isHeldByCurrentThread())
lock.unlock();
}
}
}
});
tA.start();
tB.start();
while(true) {
System.out.println(kp);
try {
TimeUnit.MILLISECONDS.sleep(700);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果:
A+
A+A+
A+A+A+
A+A+A+A+
A+A+A+A+A+
A+A+A+A+A+A+
A+A+A+A+A+A+A+
A+A+A+A+A+A+A+A+
A+A+A+A+A+A+A+A+A+
A+A+A+A+A+A+A+A+A+A+
A+A+A+A+A+A+A+A+A+A+A+
总结+提要
Condition就是依附于ReentrantLock锁的一个“条件”,条件和锁一起可以用来协调安排多个线程的执行,比如上述例子里边,两个线程围绕竞争一把锁,锁是可以确保只有持有锁的一个线程在执行,但Condition可以更进一步精确的让线程指定自己等待的是哪一个线程持有锁执行完了之后、自己才执行。可以理解条件是某一个锁逻辑上分解出来的更细粒度的锁。
网友评论