题目来源:学堂在线_清华大学_JAVA程序设计进阶
题目描述:
之前的同步是在子线程之间进行。
我们强制要求每一个线程都将结果写入同一个变量。
因此如果子线程在访问该变量时没有进行同步操作,结果几乎必然出错。
学员应该会观察到在前次作业中,我们只简单的令主线程休眠300毫秒,然后输出结果。
结果之所以正确,是因为我们预估到300毫秒以内,所有的子线程必然均已完成。
从原理上来说,这种设计显然是不保险的。
因此我们需要一种机制,当所有子线程均结束以后,主线程才继续运行、打印结果。
由于子线程与主线程的特殊性,我们可以使用join在处理这个任务。
本题的任务仍然是对每一个给定参数,在子线程中计算最小质因子,并将该因子累加到一个共享变量中。最后在主线程打印输出。
本题不提供输入输出样例,请仔细阅读源代码中的注释。
按照注释要求补全代码。
package chapter02;
import java.util.Scanner;
import java.lang.Exception;
import java.lang.InterruptedException;
public class test03 {
//直接定义一个基本类型用于保存结果
static int result = 0;
//这个数组专门用于为同步提供对象
//因为基本类型不能直接用于同步
static int[] a = new int[0];
public static void main(String[] args) {
//根据指定的方法生成输入
int[] input = getInput();
//对每一个输入的参数,创建并执行一个子线程
for (final int n : input) {
//创建一个具名对象表示一个完成指定任务的线程
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
int t = 1;
for (int i = 2; i != n + 1; ++i)
if (0 == n % i) {
t = i;
break;
}
//将t累加至结果,此处需要做同步
synchronized (a) {
result += t;
}
}
});
//执行该线程
thread.start();
//在这里敲入代码保证主线程能够正确等待直到所有子线程结束
/***begin your code here***/
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
/***end your code***/
}
//要确保子线程结束以后才在主线程打印该结果
//考虑一下在上面创建并执行子线程的时候,还应该做什么
System.out.println(result);
}
//本方法用于生成输入参数,学员可以无视
private static int[] getInput() {
Scanner cin = new Scanner(System.in);
int a = cin.nextInt();
int b = cin.nextInt();
int m = cin.nextInt();
int x = cin.nextInt();
cin.close();
int[] ret = new int[100];
for (int i = 0; i != 100; ++i) {
x = (a * x + b) % m;
ret[i] = x;
}
return ret;
}
}