多线程顺序打印问题的本质就是线程间的互斥与协作。线程互斥执行后修改阻塞条件然后唤醒阻塞线程。
1. Synchronized关键字实现
Synchronzied关键字是对Object加锁,即Object对象头指向Object Monitor(Java管程)对象。正是依赖Object Monitor,线程才能同步(互斥)的访问临界区资源。
Object Monotor提供了wait和notify/notifyAll的方法。即阻塞和唤醒线程。线程可以使用上述方法完成协作。
public class SequentialPrinting {
private int runCount = 0;
/**
* 打印机
*/
private void printABC(int id, String name) {
while (true) {
synchronized (this) {
//使用while循环保证唤醒时能够继续争夺锁
while (runCount % 3 != id) {
try {
//将该线程放入到wait_set阻塞
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(name+" ");
runCount++;
this.notifyAll();
}
}
}
public static void main(String[] args) {
SequentialPrinting sp=new SequentialPrinting ();
new Thread(()->{
sp.printABC(0,"A");
}).start();
new Thread(()->{
sp.printABC(1,"B");
}).start();
new Thread(()->{
sp.printABC(2,"C");
}).start();
}
}
2. Lock+Condition实现
public class PrintingByCondition {
private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private int runCount;
public void printABC(int id, String name) {
while (true) {
try {
lock.lock();
while (runCount % 3 != id) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(name+" ");
runCount++;
condition.signalAll();
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
PrintingByCondition printingByCondition=new PrintingByCondition();
new Thread(()->{
printingByCondition.printABC(0,"A");
}).start();
new Thread(()->{
printingByCondition.printABC(1,"B");
}).start();
new Thread(()->{
printingByCondition.printABC(2,"C");
}).start();
}
}
推荐阅读
相关阅读