线程小作业:java实现多线程协同计算一元二次方程

学校老师布置了两个和线程有关的小作业

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();
  }
}
}

运行结果:
每次运行结果不完全一致,有时候一样,有时不一样。且执行顺序也不一样。
原因:
多线程之间访问了相同的数据,此时线程之间属于竞争状态,谁先抢到就运行一个时间片,然后到下一个时间片再抢,所以,结果不会唯一。
运行结果1
运行结果2
运行结果3
运行结果4
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。
result1
result2
result3
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();
 }
}

执行结果:
在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值