最近在網上看到一篇關於多線程的面試題,平時雖然有看過一些併發的理論,但是實際編碼較少,因此也是特意練習一下。
題目描述:
怎麼讓線程A、線程B、線程C順序執行?
方案一:利用線程的join()方法,join()方法是線程類的實例方法,其作用是在當前線程中調用目標線程的join()方法,則當前線程進入Waiting狀態,目標線程執行完畢後當前線程纔再次進入Runable狀態。
public class Test {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new ThreadA());
Thread t2 = new Thread(new ThreadB(t1));
Thread t3 = new Thread(new ThreadC(t2));
t1.start();
t2.start();
t3.start();
}
static class ThreadA implements Runnable {
@Override
public void run() {
System.out.println("ThreadA");
}
}
static class ThreadB implements Runnable{
private Thread thread;
public ThreadB(Thread thread) {
this.thread = thread;
}
@Override
public void run() {
try {
//目標線程先執行完才繼續執行此線程執行體
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadB");
}
}
static class ThreadC implements Runnable {
private Thread thread;
public ThreadC(Thread thread) {
this.thread = thread;
}
@Override
public void run() {
try {
//目標線程先執行完才繼續執行此線程執行體
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadC");
}
}
}
方案二:藉助線程池技術,newSingleThreadExecutor保證了其內只有一個線程在執行,且提交的線程執行體是按照FIFO的順序執行的。
public class ExecutorServiceDemo {
public static void main(String[] args) {
ExecutorService executorPool = Executors.newSingleThreadExecutor();
executorPool.submit(new ThreadA());
executorPool.submit(new ThreadB());
executorPool.submit(new ThreadC());
}
static class ThreadA implements Runnable {
@Override
public void run() {
System.out.println("ThreadA");
}
}
static class ThreadB implements Runnable{
@Override
public void run() {
System.out.println("ThreadB");
}
}
static class ThreadC implements Runnable {
@Override
public void run() {
System.out.println("ThreadC");
}
}
}
怎麼保證多個線程按順序循環執行一段代碼?
借鑑網上一種優雅的解決方案,但是原文的代碼我認爲有點問題,因爲它對線程內部的代碼加鎖對於其他線程來說是無效的。
原文鏈接:https://blog.csdn.net/feng15230805625/article/details/83350724
但是其思路是可以借鑑的,它利用鎖機制來實現對一個共享變量的互斥訪問,然後當這個共享變量等於特定值時執行特定的線程。下面是我的代碼:
對於add()方法,同一時間只能有一個線程執行它,然後在其內部持有一個計數器count,每次執行add()方法後修改計數器保證下一個線程執行add()方法。
public class CycleDemo {
private static Integer count = 0;
private synchronized static void add() {
System.out.println(Thread.currentThread().getName());
count++;
}
private static Integer get() {
return count;
}
static class ThreadA implements Runnable {
@Override
public void run() {
Thread.currentThread().setName("ThreadA");
while (true) {
if(get() % 3 == 0 && get() < 999) {
add(); //它保證了線程B在其後執行
}
}
}
}
static class ThreadB implements Runnable {
@Override
public void run() {
Thread.currentThread().setName("ThreadB");
while (true) {
if(get() % 3 == 1 && get() < 999) {
add();
}
}
}
}
static class ThreadC implements Runnable {
@Override
public void run() {
Thread.currentThread().setName("ThreadC");
while (true) {
if(get() % 3 == 2 && get() < 999) {
add();
}
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new ThreadA());
Thread t2 = new Thread(new ThreadB());
Thread t3 = new Thread(new ThreadC());
t3.start();
t2.start();
t1.start();
}
}