多种方式实现在Java中用线程轮流打印ABC
文章目录
在Java
中采用3个线程不停的轮流打印ABC这3个字符,采用不同的方式实现。
原理分析
实现思路如下:
- 要在一个
while
循环中,实现不停的打印 - 多个线程间需要依次唤醒下一个线程,实现依次打印,此时会形成死循环
- 为了打破死循环,还需要一个启动线程延后调用
代码实现
基于wait¬ify
public class ThreadPrint1Test {
public static void main(String[] args) {
new ThreadPrint1Test().testPrint();
}
public void testPrint() {
Object lockA = new Object();
Object lockB = new Object();
Object lockC = new Object();
new PrintThread("A", lockA, lockB).start();
new PrintThread("B", lockB, lockC).start();
new PrintThread("C", lockC, lockA).start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
new Thread(() -> {
synchronized (lockA) {
lockA.notify();
}
}).start();
}
class PrintThread extends Thread {
private Object waitLock;
private Object notifyLock;
private String value;
public PrintThread(String value, Object waitLock, Object notifyLock) {
this.value = value;
this.waitLock = waitLock;
this.notifyLock = notifyLock;
}
public void run() {
while (true) {
synchronized (waitLock) {
try {
waitLock.wait();
Thread.sleep(500);
System.out.println(value);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (notifyLock) {
notifyLock.notify();
}
}
}
}
}
}
基于ReentrantLock&Condition
public class ThreadPrint2Test {
public static void main(String[] args) {
new ThreadPrint2Test().testPrint();
}
public void testPrint() {
Lock lock = new ReentrantLock();
Condition conditionA = lock.newCondition();
Condition conditionB = lock.newCondition();
Condition conditionC = lock.newCondition();
new Thread(new PrintThread("A", lock, conditionA, conditionB), "thread-a").start();
new Thread(new PrintThread("B", lock, conditionB, conditionC), "thread-b").start();
new Thread(new PrintThread("C", lock, conditionC, conditionA), "thread-c").start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
new Thread(() -> {
lock.lock();
conditionA.signal();
lock.unlock();
}, "init").start();
}
class PrintThread implements Runnable {
private Lock lock;
private Condition ca;
private Condition cb;
private String value;
public PrintThread(String value, Lock lock, Condition ca, Condition cb) {
this.value = value;
this.lock = lock;
this.ca = ca;
this.cb = cb;
}
public void run() {
while (true) {
try {
lock.lock();
ca.await();
System.out.println(value);
Thread.sleep(500);
cb.signal();
lock.unlock();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
基于Semaphore
public class ThreadPrint3Test {
public static void main(String[] args) {
new ThreadPrint3Test().testPrint();
}
public void testPrint() {
Semaphore sa = new Semaphore(1);
Semaphore sb = new Semaphore(1);
Semaphore sc = new Semaphore(1);
try {
sb.acquire();
sc.acquire();
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
new PrintThread("A", sa, sb).start();
new PrintThread("B", sb, sc).start();
new PrintThread("C", sc, sa).start();
}
class PrintThread extends Thread {
private Semaphore sa;
private Semaphore sb;
private String value;
public PrintThread(String value, Semaphore sa, Semaphore sb) {
this.value = value;
this.sa = sa;
this.sb = sb;
}
public void run() {
while (true) {
try {
sa.acquire();
System.out.println(value);
Thread.sleep(500);
sb.release();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
单个锁&volatile变量
此种方式不需要唤醒线程,同时便于很方便的修改线程数目。
public class ThreadPrint4Test {
public static void main(String[] args) {
new ThreadPrint4Test().testPrint();
}
private volatile int count = 0;
public void testPrint() {
Object lock = new Object();
new Thread(new PrintThread("A", lock), "thread-A").start();
new Thread(new PrintThread("B", lock), "thread-B").start();
new Thread(new PrintThread("C", lock), "thread-C").start();
}
class PrintThread implements Runnable {
private Object lock;
private String value;
public PrintThread(String value, Object lock) {
this.value = value;
this.lock = lock;
}
public void run() {
while (true) {
try {
synchronized (lock) {
boolean process = "A".equals(value) && count % 3 == 0;
if (process) {
count = 0;
}
process = process || ("B".equals(value) && count % 3 == 1);
process = process || ("C".equals(value) && count % 3 == 2);
if (process) {
lock.wait();
System.out.println(value);
count++;
Thread.sleep(500);
}
lock.notifyAll();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
基于LockSupport
此种方式更加简洁
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
public class ThreadPrintTestA {
public static void main(String[] args) {
PThread ta = new PThread("A");
PThread tb = new PThread("B");
PThread tc = new PThread("C");
ta.setWakeupThread(tb);
tb.setWakeupThread(tc);
tc.setWakeupThread(ta);
ta.setName("thread-1");
tb.setName("thread-2");
tc.setName("thread-3");
ta.start();
tb.start();
tc.start();
try {
TimeUnit.SECONDS.sleep(1);
LockSupport.unpark(ta);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
class PThread extends Thread {
private String str;
private Thread wakeupThread;
public PThread(String str) {
this.str = str;
}
public void setWakeupThread(Thread wakeupThread) {
this.wakeupThread = wakeupThread;
}
@Override
public void run() {
try {
while (true) {
LockSupport.park();
System.out.println(str + "\t" + currentThread().getName());
TimeUnit.MILLISECONDS.sleep(100);
LockSupport.unpark(wakeupThread);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}