Java中如何实现多线程按顺序输出ABC?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1156个文字,预计阅读时间需要5分钟。
三个线程,线程1输出A,线程2输出B,线程3输出C,让这三个线程循环有序地输出ABCABC……。看到这个题目,感觉很有意思,问题的本质是在多线程执行环境下,控制线程的执行顺序,实现有序的循环输出。下面是实现这个功能的方案:
1. 使用互斥锁(Mutex)来保证同一时间只有一个线程可以输出字符。
2.使用条件变量(Condition Variable)来控制线程的执行顺序。
3.每个线程在输出自己的字符后,等待其他线程完成输出,然后再次输出。
以下是具体的实现代码(以Python为例):
python
import threadingimport time创建互斥锁mutex=threading.Lock()创建条件变量condition=threading.Condition(mutex)
线程1def thread1(): while True: with condition: # 等待其他线程完成输出 while not (thread2_flag and thread3_flag): condition.wait() # 输出A print('A', end='') # 设置线程2和线程3的标志位 thread2_flag=True thread3_flag=True # 通知线程2和线程3 condition.notify_all()
线程2def thread2(): while True: with condition: # 等待其他线程完成输出 while not (thread1_flag and thread3_flag): condition.wait() # 输出B print('B', end='') # 设置线程1和线程3的标志位 thread1_flag=False thread3_flag=False # 通知线程1和线程3 condition.notify_all()
线程3def thread3(): while True: with condition: # 等待其他线程完成输出 while not (thread1_flag and thread2_flag): condition.wait() # 输出C print('C', end='') # 设置线程1和线程2的标志位 thread1_flag=True thread2_flag=True # 通知线程1和线程2 condition.notify_all()
初始化标志位thread1_flag=Truethread2_flag=Falsethread3_flag=False
创建线程t1=threading.Thread(target=thread1)t2=threading.Thread(target=thread2)t3=threading.Thread(target=thread3)
启动线程t1.start()t2.start()t3.start()
等待线程结束t1.join()t2.join()t3.join()
这段代码实现了三个线程循环有序输出ABC的效果。在实际应用中,可以根据需要调整线程的执行顺序和输出内容。
3个线程,线程1输出A,线程2输出B,线程3输出C,让这个3个线程循环有序地输出ABCABC…
看到这个题目,感觉很有意思,问题的本质是在多线程执行环境,控制线程的执行顺序,实现的方式有非常多种,本质上需要解决Java多线程环境下的线程执行的同步和利用锁机制来控制线程的执行顺序。
方式1:利用synchronized
这种方式也就是使用java内置的monitor机制,配合wait和notifyAll,代码如下:
(1)利用volatile做线程间资源的同步访问,同时作为线程调度的标志;
(2)利用notifyAll来唤醒其他等待当前的monitor资源的线程;
public class ThreadOrderWithSync { private volatile int flag = 'A'; private final static Object LOCK = new Object(); Runnable a = () -> { while (true) { synchronized (LOCK) { if (flag == 'A' ) { System.out.println("A"); flag = 'B'; // let other thread race to get the monitor LOCK.notifyAll(); } else { try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; Runnable b = () -> { while (true) { synchronized (LOCK) { if (flag == 'B' ) { System.out.println("B"); flag = 'C'; // let other thread race to get the monitor LOCK.notifyAll(); } else { try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; Runnable c = () -> { while (true) { synchronized (LOCK) { if (flag == 'C' ) { System.out.println("C"); flag = 'A'; // let other thread race to get the monitor LOCK.notifyAll(); } else { try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; public void runTest() { Thread ta = new Thread(a); Thread tb = new Thread(b); Thread tc = new Thread(c); ta.start(); tb.start(); tc.start(); } public static void main(String[] args) { ThreadOrderWithSync sync = new ThreadOrderWithSync(); sync.runTest(); } }
方式2:利用并发包ReentrantLock和Condition的锁机制
上面方式1的synchronized机制,因为当前的所有线程都争用同一个monitor资源,因此只能通过notifyAll来通知其他线程来加锁,因此每次都会出现race condition,但是,通过ReentrantLock的Condition,我们可以精确控制,下一个该唤醒signal的线程是哪一个(因为我们知道执行的顺序是A->B->C的循环),相比synchronized的机制,Condition机制可以更精细化线程的调度设计,代码示例如下:
/** * @author xijin.zeng created on 2018/8/31 * Thrads runing order: A->B->C */ public class ThreadOrderWithCondition { private static final ReentrantLock LOCK = new ReentrantLock(); private static final Condition C_A = LOCK.newCondition(); private static final Condition C_B = LOCK.newCondition(); private static final Condition C_C = LOCK.newCondition(); /** * init for A to run first */ private volatile int flag = 'A'; Runnable a = () -> { while (true) { LOCK.lock(); if (flag == 'A') { System.out.println("A"); flag = 'B'; // signal B to run C_B.signal(); } else { try { // block and wait signal to invoke C_A.await(); } catch (InterruptedException e) { e.printStackTrace(); } } LOCK.unlock(); } }; Runnable b = () -> { while (true) { LOCK.lock(); if (flag == 'B') { System.out.println("B"); flag = 'C'; // signal C to run C_C.signal(); } else { try { // block and wait signal to invoke C_B.await(); } catch (InterruptedException e) { e.printStackTrace(); } } LOCK.unlock(); } }; Runnable c = () -> { while (true) { LOCK.lock(); if (flag == 'C') { System.out.println("C"); flag = 'A'; // signal A to run C_A.signal(); } else { try { // block and wait signal to invoke C_C.await(); } catch (InterruptedException e) { e.printStackTrace(); } } LOCK.unlock(); } }; public void runTest() { Thread threadA = new Thread(a); Thread threadB = new Thread(b); Thread threadC = new Thread(c); threadA.start(); threadB.start(); threadC.start(); } public static void main(String[] args) { ThreadOrderWithCondition o = new ThreadOrderWithCondition(); o.runTest(); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自由互联。
本文共计1156个文字,预计阅读时间需要5分钟。
三个线程,线程1输出A,线程2输出B,线程3输出C,让这三个线程循环有序地输出ABCABC……。看到这个题目,感觉很有意思,问题的本质是在多线程执行环境下,控制线程的执行顺序,实现有序的循环输出。下面是实现这个功能的方案:
1. 使用互斥锁(Mutex)来保证同一时间只有一个线程可以输出字符。
2.使用条件变量(Condition Variable)来控制线程的执行顺序。
3.每个线程在输出自己的字符后,等待其他线程完成输出,然后再次输出。
以下是具体的实现代码(以Python为例):
python
import threadingimport time创建互斥锁mutex=threading.Lock()创建条件变量condition=threading.Condition(mutex)
线程1def thread1(): while True: with condition: # 等待其他线程完成输出 while not (thread2_flag and thread3_flag): condition.wait() # 输出A print('A', end='') # 设置线程2和线程3的标志位 thread2_flag=True thread3_flag=True # 通知线程2和线程3 condition.notify_all()
线程2def thread2(): while True: with condition: # 等待其他线程完成输出 while not (thread1_flag and thread3_flag): condition.wait() # 输出B print('B', end='') # 设置线程1和线程3的标志位 thread1_flag=False thread3_flag=False # 通知线程1和线程3 condition.notify_all()
线程3def thread3(): while True: with condition: # 等待其他线程完成输出 while not (thread1_flag and thread2_flag): condition.wait() # 输出C print('C', end='') # 设置线程1和线程2的标志位 thread1_flag=True thread2_flag=True # 通知线程1和线程2 condition.notify_all()
初始化标志位thread1_flag=Truethread2_flag=Falsethread3_flag=False
创建线程t1=threading.Thread(target=thread1)t2=threading.Thread(target=thread2)t3=threading.Thread(target=thread3)
启动线程t1.start()t2.start()t3.start()
等待线程结束t1.join()t2.join()t3.join()
这段代码实现了三个线程循环有序输出ABC的效果。在实际应用中,可以根据需要调整线程的执行顺序和输出内容。
3个线程,线程1输出A,线程2输出B,线程3输出C,让这个3个线程循环有序地输出ABCABC…
看到这个题目,感觉很有意思,问题的本质是在多线程执行环境,控制线程的执行顺序,实现的方式有非常多种,本质上需要解决Java多线程环境下的线程执行的同步和利用锁机制来控制线程的执行顺序。
方式1:利用synchronized
这种方式也就是使用java内置的monitor机制,配合wait和notifyAll,代码如下:
(1)利用volatile做线程间资源的同步访问,同时作为线程调度的标志;
(2)利用notifyAll来唤醒其他等待当前的monitor资源的线程;
public class ThreadOrderWithSync { private volatile int flag = 'A'; private final static Object LOCK = new Object(); Runnable a = () -> { while (true) { synchronized (LOCK) { if (flag == 'A' ) { System.out.println("A"); flag = 'B'; // let other thread race to get the monitor LOCK.notifyAll(); } else { try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; Runnable b = () -> { while (true) { synchronized (LOCK) { if (flag == 'B' ) { System.out.println("B"); flag = 'C'; // let other thread race to get the monitor LOCK.notifyAll(); } else { try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; Runnable c = () -> { while (true) { synchronized (LOCK) { if (flag == 'C' ) { System.out.println("C"); flag = 'A'; // let other thread race to get the monitor LOCK.notifyAll(); } else { try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; public void runTest() { Thread ta = new Thread(a); Thread tb = new Thread(b); Thread tc = new Thread(c); ta.start(); tb.start(); tc.start(); } public static void main(String[] args) { ThreadOrderWithSync sync = new ThreadOrderWithSync(); sync.runTest(); } }
方式2:利用并发包ReentrantLock和Condition的锁机制
上面方式1的synchronized机制,因为当前的所有线程都争用同一个monitor资源,因此只能通过notifyAll来通知其他线程来加锁,因此每次都会出现race condition,但是,通过ReentrantLock的Condition,我们可以精确控制,下一个该唤醒signal的线程是哪一个(因为我们知道执行的顺序是A->B->C的循环),相比synchronized的机制,Condition机制可以更精细化线程的调度设计,代码示例如下:
/** * @author xijin.zeng created on 2018/8/31 * Thrads runing order: A->B->C */ public class ThreadOrderWithCondition { private static final ReentrantLock LOCK = new ReentrantLock(); private static final Condition C_A = LOCK.newCondition(); private static final Condition C_B = LOCK.newCondition(); private static final Condition C_C = LOCK.newCondition(); /** * init for A to run first */ private volatile int flag = 'A'; Runnable a = () -> { while (true) { LOCK.lock(); if (flag == 'A') { System.out.println("A"); flag = 'B'; // signal B to run C_B.signal(); } else { try { // block and wait signal to invoke C_A.await(); } catch (InterruptedException e) { e.printStackTrace(); } } LOCK.unlock(); } }; Runnable b = () -> { while (true) { LOCK.lock(); if (flag == 'B') { System.out.println("B"); flag = 'C'; // signal C to run C_C.signal(); } else { try { // block and wait signal to invoke C_B.await(); } catch (InterruptedException e) { e.printStackTrace(); } } LOCK.unlock(); } }; Runnable c = () -> { while (true) { LOCK.lock(); if (flag == 'C') { System.out.println("C"); flag = 'A'; // signal A to run C_A.signal(); } else { try { // block and wait signal to invoke C_C.await(); } catch (InterruptedException e) { e.printStackTrace(); } } LOCK.unlock(); } }; public void runTest() { Thread threadA = new Thread(a); Thread threadB = new Thread(b); Thread threadC = new Thread(c); threadA.start(); threadB.start(); threadC.start(); } public static void main(String[] args) { ThreadOrderWithCondition o = new ThreadOrderWithCondition(); o.runTest(); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自由互联。

