有三组数据:
第 1 组:ABCDEFGHI
第 2 组:123456789
第 3 组:abcdefghi
怎样输出 A1aB2bC3c… 这样的效果呢?
本篇给出 5 种实现方式,欢迎大家积极讨论,不正确之处欢迎指正。
代码中,笔者按人为理解的方式标注了代码执行的次序,便于理解。
方式1、for 死循环
package taishangcode;
/*
* 使用死循环实现3个线程交替打印A1aB2bC3c...
* 公众号:taishangcode
*/
public class ForPrint {
static volatile int a = 0;
public static void main(String[] args) {
new Thread(() -> {
for (char i = 'A'; i < 'J'; i++) {
// 等同 while(a!=0){}
for(; a!=0;) {}
System.out.print(i);
a=1;
}
}).start();
new Thread(() -> {
for (int i = 1; i < 10; i++) {
for(; a!=1;) {}
System.out.print(i);
a=2;
}
}).start();
new Thread(() -> {
for (char i = 'a'; i < 'j'; i++) {
for(; a!=2;) {}
System.out.print(i);
a=0;
}
}).start();
}
}
方式2、LockSupport
package taishangcode;
import java.util.concurrent.locks.LockSupport;
public class LockSupportPrint {
static Thread t1,t2,t3;
public static void main(String[] args) {
// 代码后面注释了执行的次序,便于理解
t1 = new Thread(() -> {
for (char i = 'A'; i < 'J'; i++) {
System.out.print(i);//1
LockSupport.unpark(t2);//1
LockSupport.park();//1
}
});
t2 = new Thread(() -> {
for (int i = 1; i < 10; i++) {
LockSupport.park();//1、2
System.out.print(i);//2
LockSupport.unpark(t3);//2
}
});
t3 = new Thread(() -> {
for (char i = 'a'; i < 'j'; i++) {
LockSupport.park();//1、3
System.out.print(i);//3
LockSupport.unpark(t1);//3
}
});
t1.start();
t2.start();
t3.start();
}
}
方式3、BlockingDeque
package taishangcode;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
/*
* 使用BlockingDeque实现3个线程交替打印A1aB2bC3c...
*/
public class BlockingDequePrint {
static BlockingDeque<String> bd1 = new LinkedBlockingDeque<String>();
static BlockingDeque<String> bd2 = new LinkedBlockingDeque<String>();
static BlockingDeque<String> bd3 = new LinkedBlockingDeque<String>();
public static void main(String[] args) {
new Thread(() -> {
try {
for (char i = 'A'; i < 'J'; i++) {
bd1.put(i + "");//1
System.out.print(bd2.take());//1-阻塞 2-取值小字母
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
for (int i = 1; i < 10; i++) {
System.out.print(bd1.take());//1-阻塞 或 1-取值成功
bd3.put(i + "");//1或2
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
for (char i = 'a'; i < 'j'; i++) {
System.out.print(bd3.take());//1-阻塞 2-取值输出数字
bd2.put(i + "");//2 执行后第一个线程执行
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
方式4、CyclicBarrier
package taishangcode;
import java.util.concurrent.CyclicBarrier;
/*
* 使用CyclicBarrier实现3个线程交替打印A1aB2bC3c...
*/
public class CyclicBarrierPrint {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
new Thread(() -> {
try {
for (char i = 'A'; i < 'J';i++) {
System.out.print(i);//1、4
cyclicBarrier.await();//1、4
cyclicBarrier.await();//2
cyclicBarrier.await();//3
}
} catch (Exception e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
for (int i = 1; i < 10;i++) {
cyclicBarrier.await();//1、4
System.out.print(i);//2
cyclicBarrier.await();//2
cyclicBarrier.await();//3
}
} catch (Exception e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
for (char i = 'a'; i < 'j';) {
cyclicBarrier.await();//1、4
cyclicBarrier.await();//2
System.out.print(i);//3
i++;//3
cyclicBarrier.await();//3
}
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
方式5、Lock 与 Condition
package taishangcode;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
* 使用Lock与Condition实现3个线程交替打印A1aB2bC3c...
*/
public class ConditionPrint {
static Lock lock = new ReentrantLock();
static Condition a = lock.newCondition();
static Condition b = lock.newCondition();
static Condition c = lock.newCondition();
static volatile int n = 1;
public static void main(String[] args) {
new Thread(() -> {
try {
lock.lock();
for (char i = 'A'; i < 'J'; i++) {
System.out.print(i);//1、3、(第6步继续从这里开始)
if (n != 1) { //第一次不通知
b.signal();//3
}
a.await();//1、3
}
b.signal(); // 唤醒最后阻塞的线程
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}).start();
new Thread(() -> {
try {
lock.lock();
for (int i = 1; i < 10; i++) {
if (n == 1) { // 该线程利用超时实现自唤醒,时间控制晚于第一个线程
b.await(10, TimeUnit.MILLISECONDS);//1
n++;
}
System.out.print(i);//2、4
c.signal();//2、4
b.await();//2、4
}
c.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}).start();
new Thread(() -> {
try {
lock.lock();
for (char i = 'a'; i < 'j'; i++) {
c.await();//1、2、5
System.out.print(i);//2、5
a.signal();//2、5
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}).start();
}
}