线程 1 输出 a 5 次,线程 2 输出 b 5 次,线程 3 输出 c 5 次。现在要求输出 abcabcabcabcabc 怎么实现
1 wait notify 版
class SynWaitNotify{
//当前输出信号
private int signal;
//输出次数
private int num;
public SynWaitNotify(int signal, int num) {
this.signal = signal;
this.num = num;
}
//输出方法
public void print(int sign,int next,String message) throws InterruptedException {
for (int i = 0; i < num; i++) {
synchronized (this){
while(signal!=sign){
this.wait();
}
System.out.print(message);
signal=next;
this.notifyAll();
}
}
}
}
@Test
public void demo1(){
SynWaitNotify synWaitNotify=new SynWaitNotify(1,10);
new Thread(()->{
try {
synWaitNotify.print(1,2,"a");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"t1").start();
new Thread(()->{
try {
synWaitNotify.print(2,3,"b");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"t2").start();
new Thread(()->{
try {
synWaitNotify.print(3,1,"c");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"t3").start();
}
2 Lock 条件变量版
class SynAwaitSignal extends ReentrantLock{
//输出次数
private int num;
public SynAwaitSignal(int num) {
this.num = num;
}
//输出方法
public void print(Condition sign,Condition next,String message) throws InterruptedException {
for (int i = 0; i < num; i++) {
this.lock();
try {
sign.await();
System.out.print(message);
next.signal();
}finally {
this.unlock();
}
}
}
//唤醒第一个线程
public void notifyFirst(Condition condition){
this.lock();
try {
condition.signal();
}finally {
this.unlock();
}
}
}
@Test
public void demo2(){
SynAwaitSignal synAwaitSignal=new SynAwaitSignal(10);
Condition condition1=synAwaitSignal.newCondition();
Condition condition2=synAwaitSignal.newCondition();
Condition condition3=synAwaitSignal.newCondition();
new Thread(()->{
try {
synAwaitSignal.print(condition1,condition2,"a");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"t1").start();
new Thread(()->{
try {
synAwaitSignal.print(condition2,condition3,"b");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"t2").start();
new Thread(()->{
try {
synAwaitSignal.print(condition3,condition1,"c");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"t3").start();
synAwaitSignal.notifyFirst(condition1);
}
注意
该实现没有考虑 a,b,c 线程都就绪再开始
2.3 Park Unpark 版
class SynParkUnpark{
//输出次数
private int num;
//下一次唤醒的线程
private int next;
//线程集合
private Thread[] list;
public SynParkUnpark(int num) {
this.num = num;
}
//将线程加入到线程数组中
public void setThreads(Thread ...threads){
list=threads;
}
//启动所有线程并唤醒指定线程
public void startThreads(Thread thread){
for (Thread th : list) {
th.start();
}
LockSupport.unpark(thread);
}
public void print(String a) {
for (int i = 0; i < num; i++) {
LockSupport.park();
System.out.print(a);
for (int j = 0; j < list.length; j++) {
if(list[j]==Thread.currentThread()){
if(j==list.length-1){
next=0;
}else{
next=j+1;
}
}
}
LockSupport.unpark(list[next]);
}
}
}
@Test
public void demo3(){
SynParkUnpark synParkUnpark=new SynParkUnpark(10);
Thread t1=new Thread(()->{
synParkUnpark.print("a");
},"t1");
Thread t2=new Thread(()->{
synParkUnpark.print("b");
},"t2");
Thread t3=new Thread(()->{
synParkUnpark.print("c");
},"t3");
synParkUnpark.setThreads(t1,t2,t3);
synParkUnpark.startThreads(t1);
}
2.4 输出
abcabcabcabcabcabcabcabcabcabc