方式1:CAS + 自旋
通过自旋切换打印
public class ThreadAlternatePrint {
// main方法
public static void main(String[] args) {
// CAS自旋打印方式
casRollPrint();
}
/**
* CAS自旋打印方式
*/
private static void casRollPrint() {
// atomic 原子类
AtomicBoolean flag = new AtomicBoolean(true);
new Thread(() -> {
for (int i = 0; i < 10; ) {
// 自旋等待
while (flag.get()) {
System.out.print("A");
// 步进 + 切换flag
i++;
flag.set(false);
}
// 让出CPU
Thread.yield();
// 依赖自旋 此处增加打印语句 可以证明
}
}).start();
new Thread(() -> {
for (int i = 0; i < 10; ) {
// 自旋等待
while (!flag.get()) {
System.out.print("B");
// 步进 + 切换flag
i++;
flag.set(true);
}
// 让出CPU
Thread.yield();
}
}).start();
}
}
方式2:volatile + 自旋
通过自旋切换打印
public class ThreadAlternatePrint {
// volatile 保证内存可见性
private static volatile boolean flag;
public static void main(String[] args) {
volatileCtlPrint();
}
private static void volatileCtlPrint() {
new Thread(() -> {
for (int i = 0; i < 10; ) {
// 自旋等待
while (!flag) {
System.out.print("A");
i++;
flag = true;
}
Thread.yield();
}
}).start();
new Thread(() -> {
for (int i = 0; i < 10; ) {
// 自旋等待
while (flag) {
System.out.print("B");
i++;
flag = false;
}
Thread.yield();
}
}).start();
}
}
方式3:synchronized + 对象锁
public class ThreadAlternatePrint {
// main方法
public static void main(String[] args) {
// synchronized打印方式
syncKeywordRollPrint();
}
private static void syncKeywordRollPrint() {
Object lock = new Object();
AtomicBoolean mark = new AtomicBoolean(false);
new Thread(() -> {
for (int i = 0; i < 10; ) {
synchronized (lock) {
while (mark.get()) {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.print("A");
i++;
mark.set(true);
lock.notifyAll();
}
}
}).start();
new Thread(() -> {
for (int i = 0; i < 10; ) {
synchronized (lock) {
while (!mark.get()) {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.print("B");
i++;
mark.set(false);
lock.notifyAll();
}
}
}).start();
}
}
public class ThreadAlternatePrint {
// main方法
public static void main(String[] args) {
// synchronized打印方式
syncKeywordRollPrint();
}
private static void syncKeywordRollPrint() {
Object lock = new Object();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
synchronized (lock) {
System.out.print("A");
lock.notifyAll();
try {
if (i == 9) {
return;
}
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}).start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
synchronized (lock) {
System.out.print("B");
lock.notifyAll();
try {
if (i == 9) {
return;
}
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}).start();
}
}
方式4:ReentrantLock + Condition
public class ThreadAlternatePrint {
// main方法
public static void main(String[] args) {
// ReentrantLock打印方式
reentrantLockRollPrint();
}
private static void reentrantLockRollPrint() {
ReentrantLock lock = new ReentrantLock(true);
Condition condition = lock.newCondition();
// 配合原子mark 不然不能保证强一致顺序
AtomicBoolean mark = new AtomicBoolean(false);
new Thread(() -> {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
while (mark.get()) {
try {
condition.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.print("A");
mark.set(true);
condition.signalAll();
} finally {
lock.unlock();
}
}
}).start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
while (!mark.get()) {
try {
condition.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.print("B");
mark.set(false);
condition.signalAll();
} finally {
lock.unlock();
}
}
}).start();
}
}
方式5:BlockingQueue
public class ThreadAlternatePrint {
// main方法
public static void main(String[] args) {
// blockQueue打印方式
blockQueueRollPrint();
}
private static void blockQueueRollPrint() {
BlockingQueue<Integer> bqA = new LinkedBlockingQueue<>(1), bqB = new LinkedBlockingQueue<>(1);
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
bqA.put(i);
System.out.print("A");
bqB.put(i);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}).start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
bqB.take();
System.out.print("B");
bqA.take();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}).start();
}
}
方式6:CyclicBarrier
public class ThreadAlternatePrint {
// main方法
public static void main(String[] args) {
// CyclicBarrier打印方式
cyclicBarrierRollPrint();
}
private static void cyclicBarrierRollPrint() {
CyclicBarrier cb = new CyclicBarrier(2);
AtomicBoolean mark = new AtomicBoolean(false);
new Thread(() -> {
for (int i = 0; i < 10; i++) {
while (mark.get()) {
}
System.out.print("A");
mark.set(true);
try {
cb.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (BrokenBarrierException e) {
throw new RuntimeException(e);
}
}
}).start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
while (!mark.get()) {
}
System.out.print("B");
mark.set(false);
try {
cb.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (BrokenBarrierException e) {
throw new RuntimeException(e);
}
}
}).start();
}
}
方式7:LockSupport
public class ThreadAlternatePrint {
static Thread th1 = null, th2 = null;
// main方法
public static void main(String[] args) {
// LockSupport打印方式
lockSupportRollPrint();
}
private static void lockSupportRollPrint() {
th1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.print("A");
LockSupport.unpark(th2);
LockSupport.park();
}
});
th2 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
LockSupport.park();
System.out.print("B");
LockSupport.unpark(th1);
}
});
th1.start();
th2.start();
}
}
方式8:信号量
public class ThreadAlternatePrint {
// main方法
public static void main(String[] args) {
// Semaphore打印方式
semaphoreRollPrint();
}
private static void semaphoreRollPrint() {
Semaphore spA = new Semaphore(1), spB = new Semaphore(0);
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
spA.acquire();
System.out.print("A");
spB.release();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}).start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
spB.acquire();
System.out.print("B");
spA.release();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}).start();
}
}