多个线程按顺序输出
来源:互联网 发布:cctv网络电视播放器 编辑:程序博客网 时间:2024/05/16 12:40
题目:编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。如:ABCABCABC……
前4种统一使用一个全局变量state进行条件控制:
(1)state初始化为1,如果state为1执行A线程,A线程修改state为2执行B线程;如果state为2执行B线程,B线程修改state为3企图执行C线程;如果state为3执行C线程,C线程修改state为1,企图执行A线程。
(2)或者state初始化为0,如果state%3==0,执行A线程;如果state%3==1,执行B线程;如果stat%3==2,执行C线程。
解法1:采用volatile修饰的全局变量state作为条件控制,用for循环加if条件判断的忙等模式。
代码实现:package com.yangliu.lock;import java.io.File;public class ABC1 {private static int n = 100000; //控制线程执行次数private volatile static int state = 0; //控制线程执行条件static class ThreadA extends Thread {public void run() { for(int i=0;i<n;){ if(state%3==0){ System.out.println("A,loopNum="+i); state++; i++; } }}}static class ThreadB extends Thread {public void run() {for(int i=0;i<n;){ if(state%3==1){ System.out.println("B,loopNum="+i); state++; i++; } }}}static class ThreadC extends Thread {public void run() {for(int i=0;i<n;){ if(state%3==2){ System.out.println("C,loopNum="+i); state++; i++; } }}}public static void main(String[] args) throws InterruptedException { long startTime = System.currentTimeMillis(); new ThreadA().start(); new ThreadB().start(); ThreadC c =new ThreadC(); c.start(); c.join(); long endTime = System.currentTimeMillis(); File f = new File("f.txt"); FileUtil.writeToFile(f, "n="+n); FileUtil.writeToFile(f, "RunTime is "+(double)(endTime-startTime)/1000+"s");}}
问题:为什么共享变量要加volatile?加volatile就足够了吗?
分析:因为加volatile可以保证变量state的可见性,上一个线程对state的修改对下一个线程是可见的。另外由于有if条件做判断,所以可以确保只有单一的线程修改变量state的值,这里用volatile就足够了。
解法2:采用原子类AtomicInteger来控制变量state,其他不变
代码实现:
package com.yangliu.lock;import java.io.File;import java.util.concurrent.atomic.AtomicInteger;public class ABC2 {private static int n = 100000; //控制线程执行次数private static AtomicInteger state = new AtomicInteger(0); //控制线程执行条件static class ThreadA extends Thread {public void run() { for(int i=0;i<n;){ if(state.get()%3==0){ System.out.println("A,loopNum="+i); state.getAndIncrement(); i++; } }}}static class ThreadB extends Thread {public void run() {for(int i=0;i<n;){if(state.get()%3==1){ System.out.println("B,loopNum="+i); state.getAndIncrement(); i++; } }}}static class ThreadC extends Thread {public void run() {for(int i=0;i<n;){if(state.get()%3==2){ System.out.println("C,loopNum="+i); state.getAndIncrement(); i++; } }}}public static void main(String[] args) throws InterruptedException { long startTime = System.currentTimeMillis(); new ThreadA().start(); new ThreadB().start(); ThreadC c =new ThreadC(); c.start(); c.join(); long endTime = System.currentTimeMillis(); File f = new File("f.txt"); FileUtil.writeToFile(f, "RunTime is "+(double)(endTime-startTime)/1000+"s");}}
解法3:采用ReentrantLock锁住整段代码
代码实现:
package com.yangliu.lock;import java.io.File;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ABC3 {private static int n = 100000; // 控制线程执行次数private static int state = 0; // 控制线程执行条件private static Lock lock = new ReentrantLock();static class ThreadA extends Thread {public void run() {for (int i = 0; i < n;) {lock.lock();if (state % 3 == 0) {System.out.println("A,loopNum=" + i);state++;i++;}lock.unlock();}}}static class ThreadB extends Thread {public void run() {for (int i = 0; i < n;) {lock.lock();if (state % 3 == 1) {System.out.println("B,loopNum=" + i);state++;i++;}lock.unlock();}}}static class ThreadC extends Thread {public void run() {for (int i = 0; i < n;) {lock.lock();if (state % 3 == 2) {System.out.println("C,loopNum=" + i);state++;i++;}lock.unlock();}}}public static void main(String[] args) throws InterruptedException { long startTime = System.currentTimeMillis(); new ThreadA().start(); new ThreadB().start(); ThreadC c =new ThreadC(); c.start(); c.join(); long endTime = System.currentTimeMillis(); File f = new File("f.txt"); FileUtil.writeToFile(f, "RunTime is "+(double)(endTime-startTime)/1000+"s");}}
解法4:采用ReentrantLock,三个Condition进行await和signal操作
代码实现:
package com.yangliu.lock;import java.io.File;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ABC4 {private static int n = 100000; // 控制线程执行次数private static Lock lock = new ReentrantLock();private static Condition A = lock.newCondition();private static Condition B = lock.newCondition();private static Condition C = lock.newCondition();private static int state = 0;private static class ThreadA extends Thread {public void run() {lock.lock();try {for (int i = 0; i < n;i++) {if (state % 3 != 0)A.await();System.out.println("A,loopNum=" + i);state++;B.signal();}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}}static class ThreadB extends Thread {public void run() {lock.lock();try {for (int i = 0; i < n;i++) {if (state % 3 != 1)B.await();System.out.println("B,loopNum=" + i);state++;C.signal();}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}}static class ThreadC extends Thread {public void run() {lock.lock();try {for (int i = 0; i < n;i++) {if (state % 3 != 2)C.await();System.out.println("C,loopNum=" + i);state++;A.signal();}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}}public static void main(String[] args) throws InterruptedException { long startTime = System.currentTimeMillis(); new ThreadA().start(); new ThreadB().start(); ThreadC c =new ThreadC(); c.start(); c.join(); long endTime = System.currentTimeMillis(); File f = new File("f.txt"); FileUtil.writeToFile(f, "RunTime is "+(double)(endTime-startTime)/1000+"s");}}
解法5:使用信号量机制,完全不用state变量进行条件控制
代码实现:
package com.yangliu.lock;import java.io.File;import java.util.concurrent.Semaphore;public class ABC5 {private static int n = 100000; private static Semaphore AB = new Semaphore(0); private static Semaphore BC = new Semaphore(0); private static Semaphore CA = new Semaphore(0); static class ThreadA extends Thread { @Override public void run() { try { for (int i = 0; i < n; i++) { CA.acquire(); System.out.println("A,loopNum=" + i); AB.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } } static class ThreadB extends Thread { @Override public void run() { try { for (int i = 0; i < n; i++) { AB.acquire(); System.out.println("B,loopNum=" + i); BC.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } } static class ThreadC extends Thread { @Override public void run() { try { for (int i = 0; i < n; i++) { BC.acquire(); System.out.println("C,loopNum=" + i); CA.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { long startTime = System.currentTimeMillis(); CA.release(); //释放CA,让A线程先执行 new ThreadA().start(); new ThreadB().start(); ThreadC c =new ThreadC(); c.start(); c.join(); long endTime = System.currentTimeMillis(); File f = new File("f.txt"); FileUtil.writeToFile(f, "RunTime is "+(double)(endTime-startTime)/1000+"s"); }}
当n取10万时的运行时间比较:
n=100000
RunTime is 5.623s
RunTime is 5.322s
RunTime is 4.482s
RunTime is 4.279s
RunTime is 3.842s
结果可知,第5种信号量机制运行时间最少,最佳。
- 多个线程按顺序输出
- 一道面试题:多个线程按顺序输出
- 按顺序输出3个线程的变量
- N个线程顺序输出,循环M遍
- 按规定顺序输出26个字母
- 多个线程按顺序执行——join()
- 顺序打印多个线程ID
- CountDownLatch 控制多个线程执行顺序
- java使用三个线程,按顺序线程1输出1、线程2输出2、线程3输出3
- 多个线程按顺序循环打印线程独有的字符串
- 线程按指定顺序输出字符到数组
- 三个线程分别打印ABC,按顺序输出ABCABC...
- 华为oj,多线程。。保证四个线程按顺序循环输出
- 开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上,要求输出结果必须按ABC的顺序显示:ABCABC
- 开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上,要求输出结果必须按ABC的顺序显示:ABCABC
- 开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上,要求输出结果必须按ABC的顺序显示:ABCABC【转载】
- 输入3个整数。按由小到大的顺序输出
- 输入 a,b,c3 个整数,按大小顺序输出
- eclipse连接MySQL
- HDU 5875 Function 线段树 || (ST表 + 二分)
- Python入门<四>
- 657. Judge Route Circle (字符串)
- 6-6 使用函数输出一个整数的逆序数
- 多个线程按顺序输出
- C#WebService返回dynamic类型报错问题
- 数据结构与算法:链表
- 【Linux学习笔记】26:环境变量
- [js高手之路]设计模式系列课程-单例模式实现模态框
- Java反射机制(reflect)
- 多列等高布局
- codeforces 849A Odds and Ends
- HDOJ HDU 1009 FatMouse' Trade