1.设计一个test.cpp,定义变量:unsigned int sum=0;创建2个线程T1和T2, T1的行为:sum+=1;T2的行为: sum+=2;当sum大于1000000时,输出sum的值,程序结束。
Q1:将该程序运行10次,记录运行结果。
Q2:10次运行结果是否一致?若不一致,请解释原因。
Q3:设计另一个autorun.cpp,它能够将test.exe运行N次(n=10000或100000…),自动收集运行结果存入result.txt文件。
Q4:是否可以消除test.exe多次运行时其结果的不一致性?请给出解决方案,测试其可行性。
2.设计一个quadratic.cpp,用于求解N个(n=10000或100000…)一元二次方程,方程的系数a、b、c为随机整数,其中a ≠ 0。将quadratic.cpp改造为采用2个线程协同求解一元二次方程的Multithreading2.cpp。
Q1:分别计算quadratic.cpp与Multithreading2.cpp的运行时间。
Q2:计算Multithreading2.cpp的加速比。
Q3:分析总结串行算法并行化改造的难点。
Q4:检索主流的支持并行计算的技术、架构与平台,简述其特点。
================================================================================
老师原意是最好让用c写,但当时还没发这么详细的作业内容。等我写到一半才发现老师发的,只能硬着头皮继续写。
后续有空会补上c的代码。
================================================================================
源代码如下
================================================================================
Q1:
1.创建两个线程,每个线程分别实现不同的功能。
package com.example.aosdemo.homework1;
/**
* 匿名线程类
*
* @author _Yuan
* @since 2020-6-15 18:40:15
*/
public class Test {
public static int sum=0;
public void runAll(){
Thread thread1 = new Thread(){
public void run(){
while(sum<=1000000){
sum+=1;//每次加1
}
System.out.println("Thread1:sum="+sum);
}
};
//线程2
Thread thread2 = new Thread(){
public void run(){
while(sum<=1000000){
sum+=2;//每次加2
}
System.out.println("Thread2:sum="+sum);
}
};
thread1.start();
thread2.start();
}
public static void main(String[] args) {
Test test = new Test();
test.runAll();
}
}
}
运行结果:
每次运行结果不完全一致,有时候一样,有时不一样。且执行顺序也不一样。
原因:
多线程之间访问了相同的数据,此时线程之间属于竞争状态,谁先抢到就运行一个时间片,然后到下一个时间片再抢,所以,结果不会唯一。
2.执行以上过程N次,并将执行结果存入txt。
package com.example.aosdemo.homework1;
import java.io.FileNotFoundException;
import java.io.PrintStream;
/**
* 匿名线程类
*
* @author _Yuan
* @since 2020-6-16 16:31:21
*/
public class Autorun {
public static final int NUM = 10000;
//将执行结果存入txt
public void wite() {
try {
PrintStream ps = new PrintStream("e:/result.txt"); // 创建一个打印输出流,输出的目标是:E盘的log.txt文件
System.setOut(ps);//把创建的打印输出流赋给系统。即系统下次向 ps输出
//循环执行
for (int i = 0; i <NUM ; i++) {
Test test = new Test();
test.runAll();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Autorun autorun = new Autorun();
autorun.wite();
}
}
运行结果:
结果不稳定,有些计算结果不一致。
3.为了解决上面的问题,我使用了线程池,串行执行所有任务。即保证所有任务的执行顺序按照任务的提交顺序执行。
package com.example.aosdemo.homework1;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 线程池SingleThreadExecutor使线程顺序执行
*
* @author _Yuan
* @since 2020-6-16 21:42:35
*/
public class ThreadPoolTest {
public static int sum = 0;
static ExecutorService executorService = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
final Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
while (sum <= 1000000) {
sum += 1;//每次加1
}
System.out.println("Thread1:sum=" + sum);
}
}
);
final Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
while (sum <= 1000000) {
sum += 2;//每次加2
}
System.out.println("Thread2:sum=" + sum);
}
}
);
executorService.submit(thread1);//线程池提交
executorService.submit(thread2);
executorService.shutdown();//关闭线程池,拒绝任务
}
}
运行结果:
执行结果始终一致为1000001,且执行顺序始终是Thread1,Thread2。
note:
解决方法不知一种,可以看下这篇文章 ----》让线程顺序执行的8种方法
================================================================================
Q2:
1.写循环求解n个一元二次方程,并添加计算运行时间的代码。封装在同一个线程类。
package com.example.aosdemo.homework2;
import java.util.Random;
/**
* 线程类:计算NUM个一元二次方程
* *note:计算结果有小数很正常,如果想要更精确的计算结果,可以使用BIgDecimal(适用于double类型的加减乘除)
* @author _Yuan
* @since 2020-6-14 18:32:13
*/
public class Mythread implements Runnable {
public static final int NUM = 10001;//方程组个数
public static int count1;//计数
public static int count2;
@Override
public void run() {
long startTime = System.currentTimeMillis(); //获取开始时间
Random random = new Random(100);//相同次数生成的随机数相同,所以必须写在for循环外面 NUM=1000时10为种子,NUM=10000时100为种子比较合适
for (int i = 1; i < NUM; i++) {
// try {
// Thread.sleep(1);//睡眠2ms,修改到一定值,可以让多个线程协同时处理任务书占比较均匀
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
task(i, random);
}
long endTime = System.currentTimeMillis(); //获取结束时间
System.out.println("程序共花费时间:" + (endTime - startTime) + "ms"); //输出程序运行时间
//判断是单线程还是多个线程协同
if ("singleThread".equals(Thread.currentThread().getName())) {
System.out.println("singleThread处理任务数:" + (count1 + count2));
} else {
System.out.println("multiThread1处理任务数:" + count1 + " multiThread2处理任务数:" + count2);
}
}
//计算一元二次方程
public void task(int i, Random random) {
// 解:x1,x2 随机参数:a,b,c 判断条件:t
int a = random.nextInt(100);//返回一个大于等于0小于100的随机数
int b = random.nextInt(100);
int c = random.nextInt(100);
double x1, x2, t;
t = b * b - 4 * a * c;//判断是否有解条件
if (a != 0) {
if (t < 0) {
System.out.println("方程组" + i + ":" + a + "X*X+" + b + "X+" + c + " 无解 " + " By " + Thread.currentThread().getName());
count1++;
} else {
x1 = ((-b) + Math.pow(t, 1 / 2)) / (2 * a);
x2 = ((-b) - Math.pow(t, 1 / 2)) / (2 * a);
System.out.println("方程组" + i + ":" + a + "X*X+" + b + "X+" + c + " 解为-->X1=" + x1 + "," + "X2=" + x2 + " " + " By " + Thread.currentThread().getName());
count2++;
}
}
}
}
2.创建创建一个单线程,并执行run方法。
package com.example.aosdemo.homework2;
/**
* 比较:单线程计算一元二次方程
* @author _Yuan
* @since 2020-6-15 00:45:05
*/
public class Quadratic {
public static void main(String[] args) {
//单线程
Mythread singleThread = new Mythread();
new Thread(singleThread,"singleThread").start();
}
}
执行结果:
3.创建一个线程类对象,两个线程都用该线程类对象实现,运行run方法实现线程的协同求解。
package com.example.aosdemo.homework2;
/**
* 比较:多线程协同计算一元二次方程
* note:由于每次执行的方程参数是随机数生成,所有不可避免每次计算结果不一样,有时单线程耗时更短
* @author _Yuan
* @since 2020-6-15 00:45:05
*/
public class Multithreading2 {
public static void main(String[] args) {
//协同多线程
Mythread multiThread = new Mythread();
new Thread(multiThread,"multiThread1").start();
new Thread(multiThread,"multiThread2").start();
}
}