三个线程交替打印 §
public class Main {
public static void main(String[] args)
throws InterruptedException {
PrintABC printABC = new PrintABC();
new Thread(() -> {printABC.printABC(0);}).start();
new Thread(() -> {printABC.printABC(1);}).start();
new Thread(() -> {printABC.printABC(2);}).start();
}
}
class PrintABC {
private static final Object LOCK = new Object();
private int num = 0;
public void printABC(int targetNum) {
for (int i = 0; i < 10;) {
synchronized (LOCK) {
while (num % 3 != targetNum) {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()
+ ": " + num);
num++;
i++;
LOCK.notifyAll();
}
}
}
}
class Join_ABC {
public static void main(String[] args)
throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread t1 = new Thread(new printABC(null), "A");
Thread t2 = new Thread(new printABC(t1), "B");
Thread t3 = new Thread(new printABC(t2), "C");
t1.start();
t2.start();
t3.start();
//这里是要保证只有t1、t2、t3为一组,进行执行才能保证t1->t2->t3的执行顺序。
Thread.sleep(10);
}
}
static class printABC implements Runnable{
private Thread beforeThread;
public printABC(Thread beforeThread) {
this.beforeThread = beforeThread;
}
@Override
public void run() {
if (beforeThread != null) {
try {
beforeThread.join();
System.out.print(
Thread.currentThread().getName());
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.print(Thread.currentThread().getName());
}
}
}
}
使用 Lock §
class Lock_ABC {
private int num;
private Lock lock = new ReentrantLock();
private void printABC(int targetNum) {
for (int i = 0; i < 10; ) {
lock.lock();
if (num % 3 == targetNum) {
num++;
i++;
System.out.print(Thread.currentThread().getName());
}
lock.unlock();
}
}
public static void main(String[] args) {
Lock_ABC lockABC = new Lock_ABC();
new Thread(() -> {
lockABC.printABC(0);
}, "A").start();
new Thread(() -> {
lockABC.printABC(1);
}, "B").start();
new Thread(() -> {
lockABC.printABC(2);
}, "C").start();
}
}
class LockConditionABC {
private int num;
private static Lock lock = new ReentrantLock();
private static Condition c1 = lock.newCondition();
private static Condition c2 = lock.newCondition();
private static Condition c3 = lock.newCondition();
private void printABC(int targetNum, Condition currentThread
, Condition nextThread) {
for (int i = 0; i < 10; ) {
lock.lock();
try {
while (num % 3 != targetNum) {
//阻塞当前线程
currentThread.await();
}
num++;
i++;
System.out.print(Thread.currentThread().getName());
// 唤醒下一个线程,而不是唤醒所有线程
nextThread.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
LockConditionABC print = new LockConditionABC();
new Thread(() -> {
print.printABC(0, c1, c2);
}, "A").start();
new Thread(() -> {
print.printABC(1, c2, c3);
}, "B").start();
new Thread(() -> {
print.printABC(2, c3, c1);
}, "C").start();
}
}
使用 Semaphore §
class SemaphoreABC {
//因为先执行线程A,所以这里设s1的计数器为1
private static Semaphore s1 = new Semaphore(1);
private static Semaphore s2 = new Semaphore(0);
private static Semaphore s3 = new Semaphore(0);
private void printABC(Semaphore currentThread
, Semaphore nextThread) {
for (int i = 0; i < 10; i++) {
try {
//阻塞当前线程,即信号量的计数器减1为0
currentThread.acquire();
System.out.println(Thread.currentThread().getName());
//唤醒下一个线程,即信号量的计数器加1
nextThread.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args)
throws InterruptedException {
SemaphoreABC printer = new SemaphoreABC();
new Thread(() -> {
printer.printABC(s1, s2);
}, "A").start();
Thread.sleep(10);
new Thread(() -> {
printer.printABC(s2, s3);
}, "B").start();
Thread.sleep(10);
new Thread(() -> {
printer.printABC(s3, s1);
}, "C").start();
}
}