0
点赞
收藏
分享

微信扫一扫

有3个线程ABC。按照ABC来运行(A线程输出A,B线程输出B,C线程输出C,以此类推,循环输出)。

自由的美人鱼 2023-07-21 阅读 33


个人记录:2018年,工作的第6到7个年头。
重点研究自己不太擅长的技术:分布式、高并发、大数据量、数据库优化、高性能、负载均衡等。
刷题是一种态度,是一种好习惯。

有3个线程ABC。按照ABC来运行(A线程输出A,B线程输出B,C线程输出C,以此类推,循环输出)。

就是线程之间的协作。请问咋做呢?这种情况是只用一个锁来实现可以吗?



个人实践


第1次:循环中,创建Thread,用join等待前一个进程结束。


写完之后,打算把Thread抽象出来。


同时,发现循环里新建Thread,就不止3个Thread了。




package cn.fansunion.threadabc;



//有3个线程ABC。按照ABC来运行(A线程输出A,B线程输出B,C线程输出C,以此类推,循环输出)。

public class ThreadABCTest1 {



 public static void main(String[] args) {

 for(int index=0;index<3;index++){

 Thread aThread = new Thread(new Runnable(){



 @Override

 public void run() {

 System.out.println("A");

 

 }

 

 });

 aThread.start();

 try {

 aThread.join();

 } catch (InterruptedException e) {

 e.printStackTrace();

 }

 Thread bThread = new Thread(new Runnable(){



 @Override

 public void run() {

 System.out.println("B");

 

 }

 

 });

 bThread.start();

 try {

 bThread.join();

 } catch (InterruptedException e) {

 e.printStackTrace();

 }

 Thread cThread = new Thread(new Runnable(){



 @Override

 public void run() {

 System.out.println("C");

 

 }

 

 });

 cThread.start();

 try {

 cThread.join();

 } catch (InterruptedException e) {

 e.printStackTrace();

 }

 }



 }



}


多次输出结果:


A

B

C

A

B

C

A

B

C



第2次:


package cn.fansunion.threadabc;



//有3个线程ABC。按照ABC来运行(A线程输出A,B线程输出B,C线程输出C,以此类推,循环输出)。

public class ThreadABCTest2 {

 

 public static void main(String[] args) {

 ThreadTask aThread = new ThreadTask("A");

 ThreadTask bThread = new ThreadTask("B");

 ThreadTask cThread = new ThreadTask("C");

 

 for(int index=0;index<10;index++){

 aThread.start();

 try {

 aThread.join();

 } catch (InterruptedException e) {

 e.printStackTrace();

 }

 bThread.start();

 try {

 bThread.join();

 } catch (InterruptedException e) {

 e.printStackTrace();

 }

 cThread.start();

 try {

 cThread.join();

 } catch (InterruptedException e) {

 e.printStackTrace();

 }

 }



 }

 

}

package cn.fansunion.threadabc;



public class ThreadTask extends Thread {



 private String word;



 public ThreadTask(String word) {

 this.word = word;

 }



 @Override

 public void run() {

 System.out.println(word);



 }



}



多次输出结果:


A

B

C

Exception in thread "main" java.lang.IllegalThreadStateException

 at java.lang.Thread.start(Thread.java:705)

 at cn.fansunion.threadabc.ThreadABCTest2.main(ThreadABCTest2.java:12)




报错原因:


join方法:Waits for this thread to die. 


调用join之后,线程就死亡了。




第3次:


3个线程,用抢占锁的方式,先后执行。




import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;



//有3个线程ABC。按照ABC来运行(A线程输出A,B线程输出B,C线程输出C,以此类推,循环输出)。

public class ThreadABCTest3 {

 

 private static Lock lock = new ReentrantLock();

 

 public static void main(String[] args) {

 ThreadTask aThread = new ThreadTask("A");

 ThreadTask bThread = new ThreadTask("B");

 ThreadTask cThread = new ThreadTask("C");

 

 for(int index=0;index<10;index++){

 lock.lock();

 aThread.start();

 lock.unlock();

 lock.lock();

 bThread.start();

 lock.unlock();

 lock.lock();

 cThread.start();

 lock.unlock();

 }

 }

 



}






多次输出结果:


A

B

C

Exception in thread "main" java.lang.IllegalThreadStateException

 at java.lang.Thread.start(Thread.java:705)

 at cn.fansunion.threadabc.ThreadABCTest3.main(ThreadABCTest3.java:18)




报错原因:


start方法也只能调用1次,尴尬了。


另外,还有1个潜在问题。(尚未证实)


start方法调用之后,线程也不是立即开始执行。


虽然aTrhead先于bThread调用start,但是不代表aThread先执行。




第4次:只创建3个线程,线程内部for循环输出。


通过lock获得锁,unlock的时候,顺序无法保证。


再次失败。


package cn.fansunion.threadabc;



import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;



//有3个线程ABC。按照ABC来运行(A线程输出A,B线程输出B,C线程输出C,以此类推,循环输出)。

public class ThreadABCTest4 {



 private static Lock lock = new ReentrantLock();



 public static void main(String[] args) {

 final int maxNum = 3;



 Thread aThread = new Thread(new Runnable() {



 @Override

 public void run() {

 for (int index = 0; index < maxNum; index++) {

 lock.lock();

 System.out.println("A");

 lock.unlock();

 }



 }



 });

 Thread bThread = new Thread(new Runnable() {



 @Override

 public void run() {

 for (int index = 0; index < maxNum; index++) {

 lock.lock();

 System.out.println("B");

 lock.unlock();

 }



 }



 });

 Thread cThread = new Thread(new Runnable() {



 @Override

 public void run() {

 for (int index = 0; index < maxNum; index++) {

 lock.lock();

 System.out.println("C");

 lock.unlock();

 }



 }



 });

 aThread.start();



 bThread.start();



 cThread.start();

 }



}




输出结果:顺序无法保证,每次结果不确定。


A

A

A

C

C

C

B

B

B





第5次:


网友提到了线程之间的协同,应该是正解。


平时,几乎没有需要写这种类型的线程协同代码。


线程本来就强调并发执行,现在非要强调先后顺序,还有必要搞多线程么。




package cn.fansunion.threadabc;



//有3个线程ABC。按照ABC来运行(A线程输出A,B线程输出B,C线程输出C,以此类推,循环输出)。

public class ThreadABCTest5 {



 public static void main(String[] args) {

 final int maxNum = 3;



 final Thread cThread = new Thread(new Runnable() {



 @Override

 public void run() {

 for (int index = 0; index < maxNum; index++) {

 try {

 wait();

 } catch (InterruptedException e) {

 e.printStackTrace();

 }

 System.out.println("C");

 }



 }



 });

 

 final Thread  bThread = new Thread(new Runnable() {



 @Override

 public void run() {

 for (int index = 0; index < maxNum; index++) {

 try {

 wait();

 } catch (InterruptedException e) {

 e.printStackTrace();

 }

 System.out.println("B");

 cThread.notify();

 }



 }



 });

 

 Thread aThread =new Thread(new Runnable() {



 @Override

 public void run() {

 for (int index = 0; index < maxNum; index++) {

 System.out.println("A");

 bThread.notify();

 }



 }



 });

 

 cThread.start();

 bThread.start();

 aThread.start();

 



 }



}





 运行结果:


Exception in thread "Thread-0" Exception in thread "Thread-1" A

java.lang.IllegalMonitorStateException

 at java.lang.Object.wait(Native Method)

 at java.lang.Object.wait(Object.java:502)

 at cn.fansunion.threadabc.ThreadABCTest5$1.run(ThreadABCTest5.java:20)

 at java.lang.Thread.run(Thread.java:745)

Exception in thread "Thread-2" java.lang.IllegalMonitorStateException

 at java.lang.Object.notify(Native Method)

 at cn.fansunion.threadabc.ThreadABCTest5$3.run(ThreadABCTest5.java:55)

 at java.lang.Thread.run(Thread.java:745)

java.lang.IllegalMonitorStateException

 at java.lang.Object.wait(Native Method)

 at java.lang.Object.wait(Object.java:502)

 at cn.fansunion.threadabc.ThreadABCTest5$2.run(ThreadABCTest5.java:37)

 at java.lang.Thread.run(Thread.java:745)




语法不熟悉啊。哎。




果然啊,我还是最菜的。




我刷题,我骄傲。



举报

相关推荐

0 条评论