多线程实现加法(三种创建线程的方式)

文章目录

  • 三种创建线程的方法
    • 继承Thread类(没有返回值)
    • 实现Runable接口(没有返回值)
    • 实现Callable接口(有返回值)
  • CountDownLatch

三种创建线程的方法

利用多线程去计算加法,主要有三步

  • 分解任务为子任务
  • 新建线程执行子任务(如何得到结果或保存结果)
  • 得到子任务的结果,合并得到最终结果

创建线程主要有三种方法,前两种没有返回值,callable接口有返回值。

继承Thread类(没有返回值)

//继承thread类,需要重写run方法
public class SumThread extends Thread {
    private long start;
    private long end;
    private int num;
    private long[] result;
    //这个是为了判断所有线程是否全部执行完,因为继承thread类的线程没有返回值
    private CountDownLatch cdl;

    public SumThread(long start, long end, int num, long[] result, CountDownLatch cdl) {
        this.start = start;
        this.end = end;
        this.num = num;
        this.result = result;
        this.cdl = cdl;
    }
    //需要重写run方法
    @Override
    public void run() {
        long sum = 0;
        for (long i=start;i<end;i++){
            sum += i;
        }
        result[num] = sum;
        //计数器减一
        cdl.countDown();
    }
}
public class SumParallelThread {
    public static void main(String[] args) throws InterruptedException{
        int N = 90000000;
        int numThread = 3;
        parallel(N, numThread);
    }
    public static void parallel(int N, int numThread) throws InterruptedException{
        //通过一个数组来记录各个子线程的计算结果
        long[] result = new long[numThread];
        //CountDownLatch可以看作计数器
        CountDownLatch cdl = new CountDownLatch(numThread);
        long start = System.currentTimeMillis();
        for (int i=0;i<numThread;i++){
            //新建线程,start方法启动线程
            SumThread thread = new SumThread(i*N/numThread, (i+1)*N/numThread, i, result, cdl);
            thread.start();
        }
        //等待所有线程执行完毕,在进行最后的加法
        cdl.await();
        long sum = 0;
        for (long r : result)
            sum += r;
        long end = System.currentTimeMillis();
        System.out.println("并行计算结果:"+sum);
        System.out.println("并行计算时间:"+(end-start)+"ms");
    }
}

实现Runable接口(没有返回值)

public class SumThreadRunnable implements Runnable {
    private long start;
    private long end;
    private long[] result;
    private CountDownLatch cdl;
    private int num;
    public SumThreadRunnable(long start, long end, long[] result, CountDownLatch cdl, int num){
        this.start = start;
        this.end = end;
        this.result = result;
        this.cdl = cdl;
        this.num = num;
    }
    //重写run方法
    @Override
    public void run() {
        long sum = 0;
        for (long i=start;i<=end;i++){
            sum += i;
        }
        result[num] = sum;
        cdl.countDown();
    }
}
public class SumParallelRunnable {
    public static void main(String[] args) throws InterruptedException{
        int N = 90000000;
        int numThread = 3;
        countDownLatchSum(N, numThread);
    }
    public static void countDownLatchSum(int N, int numThread) throws InterruptedException{
        long start = System.currentTimeMillis();
        //这个对象也是为了判断所有子线程是否全部执行完成
        CountDownLatch cdl = new CountDownLatch(numThread);
        //和上一个一样,使用一个数组来保存子线程的计算结果
        long[] result = new long[numThread];
        long sum = 0;
        for (int i=0;i<numThread;i++){
            //runable作为target去新建线程,调用start方法执行子线程
            new Thread(new SumThreadRunnable(i*N/numThread, (i+1)*N/numThread, result, cdl, i)).start();
        }
        cdl.await();
        for (long r : result)
            sum += r;
        long end = System.currentTimeMillis();
        System.out.println("并行计算耗时:"+(end-start)+"ms");
        System.out.println("并行计算结果:"+sum);
    }
}

实现Callable接口(有返回值)

public class SumThreadCallable implements Callable<Long> {
    private long start;
    private long end;
    public SumThreadCallable(long start, long end){
        this.start = start;
        this.end = end;
    }
    //重写call方法,会有返回值
    @Override
    public Long call() throws Exception {
        long sum = 0;
        for (long i=start;i<end;i++){
            sum += i;
        }
        return sum;
    }
}
public class SumParallelCallable {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        int numThread = 3;
        int N = 90000000;
        parallel(N, numThread);
    }
    public static void parallel(int N, int numThread) throws ExecutionException, InterruptedException{
        //新建线程池
        ExecutorService executor = Executors.newFixedThreadPool(numThread);
        long start1 = System.currentTimeMillis();
        //使用Future记录返回值
        List<Future<Long>> ans = new ArrayList<>();
        for (int i=0;i<numThread;i++){
            //使用submit向线程池提交线程,会有返回值
            //使用execute提交的线程,没有返回值
            Future<Long> a = executor.submit(new SumThreadCallable(i*N/numThread, (i+1)*N/numThread));
            ans.add(a);
        }
        long sum = 0;
        for (Future<Long> i : ans){
            long tmp = i.get();
            System.out.println("线程"+i+"的结果是:"+tmp);
            sum += tmp;
        }
        long end1 = System.currentTimeMillis();
        System.out.println("并行计算耗时:"+(end1-start1)+"ms");
        System.out.println("并行计算结果:"+sum);
    }
}

CountDownLatch

countDownLatch 像是一个计数器,线程完成一个记录一个,计数器递减,只能使用一次。
可以用来控制线程按顺序执行,主要有以下几个方法:

//构造方法,count是计数器的初值
public CountDownLatch(int count) {};
//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public void await() throws InterruptedException { };   
//和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  
//将count值减1
public void countDown() {};

你可能感兴趣的:(并发编程)