方法一:通过 synchronized 锁和 wait notify的方式实现
public class ThreadTest {
public static void main(String[] args) {
AtomicInteger executeThreadNo = new AtomicInteger(0);
AtomicInteger printI = new AtomicInteger(1);
int total = 3;
Thread t1 = new Thread(new PrintRunnable(0, executeThreadNo, total, printI));
Thread t2 = new Thread(new PrintRunnable(1, executeThreadNo, total, printI));
Thread t3 = new Thread(new PrintRunnable(2, executeThreadNo, total, printI));
t2.start();
t1.start();
t3.start();
}
class PrintRunnable implements Runnable {
private int threadNo;
private AtomicInteger executeThreadNo;
private int total;
private AtomicInteger printI;
public PrintRunnable(int threadNo, AtomicInteger executeThreadNo, int total, AtomicInteger printI) {
this.threadNo = threadNo;
this.executeThreadNo = executeThreadNo;
this.total = total;
this.printI = printI;
}
@Override
public void run() {
while (true) {
synchronized (executeThreadNo) {
try {
while (executeThreadNo != null && threadNo != executeThreadNo.get()) {
executeThreadNo.wait();
}
} catch (InterruptedException e) {
System.out.println("中断异常");
}
if (printI.get() <= 100) {
System.out.println(Thread.currentThread().getName() + "****** " + printI.get());
printI.addAndGet(1);
executeThreadNo.set((executeThreadNo.get() + total + 1) % total);
executeThreadNo.notifyAll();
} else {
executeThreadNo.set((executeThreadNo.get() + total + 1) % total);
executeThreadNo.notifyAll();
return;
}
}
}
}
}
方法二:通过可重入锁和condition条件的方式实现
public class ThreadTest2 {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
AtomicInteger executeThreadNo = new AtomicInteger(0);
AtomicInteger printI = new AtomicInteger(1);
int total = 3;
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition c3 = lock.newCondition();
Thread t1 = new Thread(new PrintRunnable2(lock, c1, c2, c3, 0, executeThreadNo, total, printI));
Thread t2 = new Thread(new PrintRunnable2(lock, c1, c2, c3, 1, executeThreadNo, total, printI));
Thread t3 = new Thread(new PrintRunnable2(lock, c1, c2, c3, 2, executeThreadNo, total, printI));
t2.start();
t1.start();
t3.start();
}
}
class PrintRunnable2 implements Runnable {
private ReentrantLock reentrantLock;
private Condition c1;
private Condition c2;
private Condition c3;
private int threadNo;
private AtomicInteger executeThreadNo;
private int total;
private AtomicInteger printI;
public PrintRunnable2(ReentrantLock reentrantLock, Condition c1, Condition c2, Condition c3, int threadNo, AtomicInteger executeThreadNo, int total, AtomicInteger printI) {
this.reentrantLock = reentrantLock;
this.c1 = c1;
this.c2 = c2;
this.c3 = c3;
this.threadNo = threadNo;
this.executeThreadNo = executeThreadNo;
this.total = total;
this.printI = printI;
}
@Override
public void run() {
while (true) {
try {
reentrantLock.lock();
if (executeThreadNo.get() != threadNo) {
if (threadNo == 0) {
c1.await();
} else if (threadNo == 1) {
c2.await();
} else if (threadNo == 2) {
c3.await();
}
}
if (printI.get() <= 100) {
System.out.println(Thread.currentThread().getName() + "****** " + printI.get());
printI.addAndGet(1);
executeThreadNo.set((executeThreadNo.get() + total + 1) % total);
} else {
return;
}
} catch (InterruptedException e) {
System.out.println("中断异常");
} finally {
signal();
}
}
}
private void signal() {
if (threadNo == 0) {
c2.signal();
} else if (threadNo == 1) {
c3.signal();
} else {
c1.signal();
}
reentrantLock.unlock();
}
}