还未曾想过死循环的条件break机制能在流程控制以外的场景中焕发光彩。
问题描述
有四个线程,每个线程函数都能够接收三个整型变量(变量的值在创建线程时设定),在线程内部求出三个变量的和,在四个线程都计算完毕后,要求必须在main函数中对四个线程的计算结果再次求出总和,然后在各个线程中分别输出这个总和值。
方案逻辑 程序开始运行后,主线程与子线程的协作可以这样描述:
子线程计算变量之和,主线程进入死循环,检测子线程是否计算完成。
子线程计算完成时,主线程计算总和并跳出循环,此时子线程进入死循环,检测主线程是否计算完成。
主线程计算完成后即结束运行,各个子线程输出总和。
步骤
主线程
子线程
①
启动,初始化数据
②
循环等待子线程通知
启动,各子线程计算变量之和 循环等待 各子线程计算完毕后通知主线程 跳出循环
③
对子线程结果再次求和 通知子线程 跳出循环
循环等待主线程通知
④
结束
输出结果 跳出循环
⑤
结束
两种检测都各需要一个flag作为判断条件,而且需要一个共享的空间用于保存子线程和主线程计算的结果,在需要取用时从中获取即可。
实现代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Main { public static void main (String[] args) { Thread[] thread = new Thread [4 ]; for (int i = 1 ; i <= thread.length; i++) thread[i - 1 ] = new Thread (new Task (i, i, i)); for (int i = 1 ; i <= thread.length; i++) thread[i - 1 ].start(); while (true ) { if (Data.isSubFinished()) { for (int sub : Data.getArrayList()) Data.setSum(Data.getSum() + sub); Data.finishSum(); break ; } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public class Task implements Runnable { private final int a; private final int b; private final int c; public Task (int a, int b, int c) { this .a = a; this .b = b; this .c = c; } @Override public void run () { int sum = a + b + c; Data.addList(sum); while (true ) { if (Data.getListLength() == 4 ) { Data.finishSub(); break ; } } while (true ) { if (Data.isSumFinished()) { System.out.println( "In " + Thread.currentThread().getName() + ", the sum is: " + Data.getSum() ); break ; } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 public class Data { private static final ArrayList<Integer> arrayList = new ArrayList <>(); private static int sum = 0 ; private static boolean flagSub = false ; private static boolean flagSum = false ; public static synchronized void addList (Integer sum) { arrayList.add(sum); } public static ArrayList<Integer> getArrayList () { return arrayList; } public static int getListLength () { return arrayList.size(); } public static void setSum (int sum) { Data.sum = sum; } public static int getSum () { return sum; } public static void finishSub () { flagSub = true ; } public static void finishSum () { flagSum = true ; } public static boolean isSubFinished () { return flagSub; } public static boolean isSumFinished () { return flagSum; } }
运行结果 1 2 3 4 In Thread-1 , the sum is: 30 In Thread-0 , the sum is: 30 In Thread-3 , the sum is: 30 In Thread-2 , the sum is: 30