一、标志变量 + 互斥锁
标志变量用于标识当前应该是哪个线程进行输出,互斥锁用于保证对标志变量的互斥访问。
public class Main {
private static int globalTag = 0; // 标志变量
private static final Lock LOCK = new ReentrantLock(); // 互斥锁
private static final int TIMES = 10;
@Data
@Accessors(chain = true)
private static class MyRunnable implements Runnable {
private int myTag;
@Override
public void run() {
for (int i = 0; i < TIMES; i++) {
try {
// 加锁
LOCK.lock();
// 让权等待
while (myTag != globalTag) {
LOCK.unlock();
Thread.yield();
LOCK.lock();
}
// 输出
System.out.print(myTag + 1);
// 修改标志位
globalTag = (globalTag + 1) % 3;
} finally {
// 解锁
LOCK.unlock();
}
}
}
}
public static void main(String[] args) {
new Thread(new MyRunnable().setMyTag(0)).start();
new Thread(new MyRunnable().setMyTag(1)).start();
new Thread(new MyRunnable().setMyTag(2)).start();
}
}
二、标志变量 + 互斥锁 + 条件变量
public class Main {
private static int globalTag = 0; // 标志变量
private static final Lock LOCK = new ReentrantLock(); // 互斥锁
private static final Condition CONDITION = LOCK.newCondition(); // 条件变量
private static final int TIMES = 10;
@Data
@Accessors(chain = true)
private static class MyRunnable implements Runnable {
private int myTag;
@Override
public void run() {
for (int i = 0; i < TIMES; i++) {
try {
// 加锁
LOCK.lock();
// 让权等待
while (myTag != globalTag) {
CONDITION.await();
}
// 输出
System.out.print(myTag + 1);
// 修改标志位
globalTag = (globalTag + 1) % 3;
// 唤醒其他等待的线程
CONDITION.signalAll();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
// 解锁
LOCK.unlock();
}
}
}
}
public static void main(String[] args) {
new Thread(new MyRunnable().setMyTag(0)).start();
new Thread(new MyRunnable().setMyTag(1)).start();
new Thread(new MyRunnable().setMyTag(2)).start();
}
}
三、标志变量 + synchronized
public class Main {
private static int globalTag = 0; // 标志变量
private static final int TIMES = 10;
@Data
@Accessors(chain = true)
private static class MyRunnable implements Runnable {
private int myTag;
@Override
public void run() {
for (int i = 0; i < TIMES; i++) {
while (true) {
synchronized (MyRunnable.class) {
if (myTag == globalTag) {
// 输出
System.out.print(myTag + 1);
// 修改标志位
globalTag = (globalTag + 1) % 3;
// 退出循环
break;
}
}
}
}
}
}
public static void main(String[] args) {
new Thread(new MyRunnable().setMyTag(0)).start();
new Thread(new MyRunnable().setMyTag(1)).start();
new Thread(new MyRunnable().setMyTag(2)).start();
}
}
四、原子变量
public class Main {
private static final AtomicInteger GLOBAL_TAG = new AtomicInteger(0);
private static final int TIMES = 10;
@Data
@Accessors(chain = true)
private static class MyRunnable implements Runnable {
private int myTag;
@Override
public void run() {
for (int i = 0; i < TIMES; i++) {
// 让权等待
while (GLOBAL_TAG.get() != myTag) {
Thread.yield();
}
// 输出
System.out.print(myTag + 1);
// 修改标志位
GLOBAL_TAG.set((GLOBAL_TAG.get() + 1) % 3);
}
}
}
public static void main(String[] args) {
new Thread(new MyRunnable().setMyTag(0)).start();
new Thread(new MyRunnable().setMyTag(1)).start();
new Thread(new MyRunnable().setMyTag(2)).start();
}
}
五、volatile
public class Main {
private static volatile int GLOBAL_TAG = 0;
private static final int TIMES = 10;
@Data
@Accessors(chain = true)
private static class MyRunnable implements Runnable {
private int myTag;
@Override
public void run() {
for (int i = 0; i < TIMES; i++) {
// 让权等待
while (GLOBAL_TAG != myTag) {
Thread.yield();
}
// 输出
System.out.print(myTag + 1);
// 修改标志位
GLOBAL_TAG = (myTag + 1) % 3;
}
}
}
public static void main(String[] args) {
new Thread(new MyRunnable().setMyTag(0)).start();
new Thread(new MyRunnable().setMyTag(1)).start();
new Thread(new MyRunnable().setMyTag(2)).start();
}
}
六、信号量
public class Main {
private static final Semaphore[] semaphores = new Semaphore[3];
private static final int TIMES = 10;
static {
semaphores[0] = new Semaphore(1);
semaphores[1] = new Semaphore(0);
semaphores[2] = new Semaphore(0);
}
@Data
@Accessors(chain = true)
private static class MyRunnable implements Runnable {
private int myTag;
@Override
public void run() {
try {
for (int i = 0; i < TIMES; i++) {
// 获取信号量
semaphores[myTag].acquire();
// 输出
System.out.print(myTag + 1);
// 释放信号量
semaphores[(myTag + 1) % 3].release();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public static void main(String[] args) {
new Thread(new MyRunnable().setMyTag(0)).start();
new Thread(new MyRunnable().setMyTag(1)).start();
new Thread(new MyRunnable().setMyTag(2)).start();
}
}