需求
使用三个线程,1,2,3,分别负责打印A,B,C,打印10次。
分析
分析锁的获取和释放和通知,线程堵塞
方式1,使用ReentrantLock
使用ReentrantLock(true)公平锁,再设置操作的标志位current(A,B,C),当current和当前线程负责打印的字段相同,执行操作,否则释放锁,执行完,释放锁,代码如下:
public class PrintABCTask extends Thread {
private static ReentrantLock lock = new ReentrantLock(true);
private static String current = "A";
/**
* 私有字段
*/
private String value;
public PrintABCTask(String name, String value) {
super(name);
this.value = value;
}
@Override
public void run() {
for (int i = 0; i < 10; ) {
lock.lock();
// 条件判断通过while,而不是if,但是用if通常好像也没出现过问题
while (current.equalsIgnoreCase(value)) {
System.out.printf("%s:%s\t", getName(), value);
current = next(current);
i++;
}
lock.unlock();
}
}
private static String next(String current) {
switch (current) {
case "A":
return "B";
case "B":
return "C";
case "C":
return "A";
}
throw new RuntimeException("invalid params:" + current);
}
}
测试代码
public class PrintABCOnTurn {
public static void main(String[] args) {
PrintABCTask task_A = new PrintABCTask("T-1", "A");
PrintABCTask task_B = new PrintABCTask("T-2", "B");
PrintABCTask task_C = new PrintABCTask("T-3", "C");
// 顺序可以替换
task_C.start();
task_B.start();
task_A.start();
}
}
方式2:Synchronized
实现方式和上面是一样的,只是将加锁方式换作了synchronized
synchronized (lock) {
// 条件判断通过while,而不是if,但是用if通常好像也没出现过问题
while (current.equalsIgnoreCase(value)) {
System.out.printf("%s:%s\t", getName(), value);
current = next(current);
i++;
}
lock.notifyAll();
}