Java使用5个线程计算数组之和

前言

之前写过多线程累加计数,原理跟本篇类似,传送门

累加计数比计算数组之和逻辑稍微简单一点,如果对于这块不熟悉的,可以先看下累加计数。

基本思想已经在之前那篇文章里写过了,这里就直接贴代码了。

这里分别通过自己创建线程来实现功能,还有通过线程池来实现功能。思想都差不多。只是代码写法略有不同。仅供参考。

代码一:

五个线程交替累加计算数组之和,这种方法其实不如单线程直接累加快,因为交替累加需要前一个线程计算的结果。

package test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class FiveThreadCount {
 private int count=0;
 private int[] arr={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};
 private int j=0;
 //定义一个任务,关键点所在
 private class MyThread extends Thread{
  @Override
  public void run() {
   super.run();
    while(j<arr.length)
    {
     synchronized (MyThread.class) {
      if(j>=arr.length){
       return;
      }
      count+=arr[j++];
      try {
       Thread.sleep(100);
      } catch (InterruptedException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
      System.out.println(Thread.currentThread().getName());
     }
    }
  }
 }

 //方法一
 public void test1(){
  for(int i=0;i<5;i++){
   new MyThread().start();
  }
        try {
   Thread.sleep(10000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
        System.out.println(count);
 }
 //方法二
 public void test2(){
  Thread myThread=new MyThread();
  for(int i=0;i<5;i++){
   new Thread(myThread).start();
  }
        try {
   Thread.sleep(10000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
        System.out.println(count);
 }
 //方法一的线程池实现版
 public void test3(){
  ExecutorService service=Executors.newCachedThreadPool();
  for(int i=0;i<5;i++){
   service.execute(new MyThread());
  }
        try {
   Thread.sleep(10000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
        System.out.println(count);
 }
 //方法二的线程池实现版
 public void test4(){
  ExecutorService service=Executors.newCachedThreadPool();
  Thread myThread=new MyThread();
  for(int i=0;i<5;i++){
   service.execute(myThread);
  }
        try {
   Thread.sleep(10000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
        System.out.println(count);
 }

}

上边代码中,用到了sleep方法的原因,sleep(100)是为了让其他线程有时间执行任务,如果不sleep的话,有可能一个线程就全部执行完了。 最后的sleep(10000)是为了等所有线程执行完后,打印最后的计算结果。

代码二:

将数组分为5等分,让每个线程计算自己负责的那份,并发计算,最后汇总结果。这种方式比代码一速度会快些。因为线程独立计算,不依赖其他线程的结果。最后几个线程将总数累加即可。

方式一:

使用Callable,FutureTask方式,来实现代码:

package test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class FiveThreadCount2 {
 private int[] arr={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};
 private int total=0;
 public void test() throws InterruptedException, ExecutionException{
  ExecutorService service=Executors.newFixedThreadPool(5);
  int length=arr.length;
  for(int j=0;j<length;j+=(length/5)){
   FutureTask<Integer> task;
   if( (j+(length/5))<length){
    task=new FutureTask<Integer>(new MyCallable(arr, j, j+(length/5)));
   }else{
    task=new FutureTask<Integer>(new MyCallable(arr, j, length));
   }
   service.execute(task);
   total+=task.get();
  }
  service.shutdown();
  System.out.println(total);

 }

 public class MyCallable implements Callable<Integer>{
  int[] arr;
  int startIndex;
  int endIndex;
  public MyCallable(int[] arr,int startIndex,int endIndex){
   this.arr=arr;
   this.startIndex=startIndex;
   this.endIndex=endIndex;
  }
  @Override
  public Integer call() throws Exception {
   int sum=0;
   for(int i=startIndex;i<endIndex;i++){
    sum+=arr[i];
   }
   System.out.println(Thread.currentThread().getName());
   return sum;
  }
 }

}

这个方式有一个缺点,看似5个线程异步执行,其实是顺序执行,因为 task.get是要等待线程执行完毕才会执行下边的代码。所以效率不会高,可能换种写法可以解决这个问题,这里就不深入研究。

方式二:

通过java工具类CountDownLatch实现并发计算

package test;

import java.util.concurrent.CountDownLatch;

public class FiveThreadCount3 {
 private int[] arr={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};
 private int total=0;
 public void test() throws InterruptedException{
  int length=arr.length;
  CountDownLatch latch=new CountDownLatch(length%5==0?5:6);
  System.out.println(length);
  for(int j=0;j<length;j+=(length/5)){
   MyThread task;
   if( (j+(length/5))<=length){
    task=new MyThread(arr, j, j+(length/5), latch);
   }else{
    task=new MyThread(arr, j, length, latch);
   }
   new Thread(task).start();
  }
  latch.await();
  System.out.println(total);
 }

 private class MyThread implements Runnable{
  int[] arr;
  int startIndex;
  int endIndex;
  CountDownLatch latch;
  public MyThread(int[] arr,int startIndex,int endIndex,CountDownLatch latch){
   this.arr=arr;
   this.startIndex=startIndex;
   this.endIndex=endIndex;
   this.latch=latch;
  }
  @Override
  public void run() {
   int sum=0;
   for(int i=startIndex;i<endIndex;i++){
    sum+=arr[i];
   }
   synchronized (MyThread.class) {
    total+=sum;
   }

   System.out.println(Thread.currentThread().getName());
   latch.countDown();

  }

 }
}

对于CountDownLatch不熟悉的可以搜索下用法。

方式三:

通过java工具类 CyclicBarrier实现并发计算。

package test;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class FiveThreadCount1 {
 private int[] arr={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};
 private int total=0;
 public void test() throws InterruptedException, BrokenBarrierException{
  int length=arr.length;
  CyclicBarrier barrier=new CyclicBarrier((length%5==0?5:6)+1);
  System.out.println(length);
  for(int j=0;j<length;j+=(length/5)){
   MyThread task;
   if( (j+(length/5))<=length){
    task=new MyThread(arr, j, j+(length/5), barrier);
   }else{
    task=new MyThread(arr, j, length, barrier);
   }
   new Thread(task).start();
  }
  barrier.await();
  System.out.println(total);
 }

 private class MyThread implements Runnable{
  int[] arr;
  int startIndex;
  int endIndex;
  CyclicBarrier barrier;
  public MyThread(int[] arr,int startIndex,int endIndex,CyclicBarrier barrier){
   this.arr=arr;
   this.startIndex=startIndex;
   this.endIndex=endIndex;
   this.barrier=barrier;
  }
  @Override
  public void run() {
   int sum=0;
   for(int i=startIndex;i<endIndex;i++){
    sum+=arr[i];
   }
   synchronized (MyThread.class) {
    total+=sum;
   }

   try {
    System.out.println(Thread.currentThread().getName());
    barrier.await();
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } catch (BrokenBarrierException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }

 }
}

总结

总体来说,代码二的方式二、三,效率会高一点。以上代码都是通过main方法调用示例代码的test方法,输出结果到控制台。

到此这篇关于Java使用5个线程计算数组之和的文章就介绍到这了,更多相关Java 线程数组之和内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java 实现随机数组输出及求和实例详解

    java 实现随机数组输出及求和 问题描述: 随机生成10个数,填充一个数组,然后用消息框显示数组内容,接着计算数组元素的和,将结果也显示在消息框中. 设计思路: 使用java.util中的Random类来获取随机数,存入数组后,定义一个String类的对象result,利用for循环存储要输出的数组内容到result并且求和:再利用javax.swing中的JoptionPane类创建消息框进行结果输出. 源代码: import java.util.*; import javax.swing.

  • Java生成10个1000以内的随机数并用消息框显示数组内容然后求和输出

    本文最终结果大概是这样的,使用java技术随机生成10个数,然后填充一个数组并在消息框中显示数组内容,接着对数组求和输出,将结果显示在消息框中. 设计思路:可以先用Math.Random()*1000生成1000以内随机数,然后依次存入数组中,然后读取数组,输出随机数,同时进行加法计算,最后将所有结果以消息框形式输出. 程序流程图: 源代码: package 随机数求和; import javax.swing.*; public class Sum { public static void ma

  • Java数组的遍历与求和知识点

    一维数组遍历与求和: public class OneArry{ public static void main(String[] args) { double[] num = {1.9, 2.9, 3.4, 3.5,10,-1}; num[0]=new Double(2); //通过下标把1.9变为2.0 double sum = 0; for (int i = 0; i < num.length; i++) { //遍历 System.out.println(num[i]); sum+=nu

  • Java使用5个线程计算数组之和

    前言 之前写过多线程累加计数,原理跟本篇类似,传送门 累加计数比计算数组之和逻辑稍微简单一点,如果对于这块不熟悉的,可以先看下累加计数. 基本思想已经在之前那篇文章里写过了,这里就直接贴代码了. 这里分别通过自己创建线程来实现功能,还有通过线程池来实现功能.思想都差不多.只是代码写法略有不同.仅供参考. 代码一: 五个线程交替累加计算数组之和,这种方法其实不如单线程直接累加快,因为交替累加需要前一个线程计算的结果. package test; import java.util.concurren

  • 详解java各种集合的线程安全

    线程安全 首先要明白线程的工作原理,jvm有一个main memory,而每个线程有自己的working memory,一个线程对一个variable进行操作时,都要在自己的working memory里面建立一个copy,操作完之后再写入main memory.多个线程同时操作同一个variable,就可能会出现不可预知的结果.根据上面的解释,很容易想出相应的scenario. 而用synchronized的关键是建立一个monitor,这个monitor可以是要修改的variable也可以其

  • Java Atomic类及线程同步新机制原理解析

    一.为什么要使用Atomic类? 看一下下面这个小程序,模拟计数,创建10个线程,共同访问这个int count = 0 :每个线程给count往上加10000,这个时候你需要加锁,如果不加锁会出现线程安全问题,但是使用AtomicInteger之后就不用再做加锁的操作了,因为AtomicInteger内部使用了CAS操作,直接无锁往上递增,有人会问问什么会出现无锁操作,答案只有一个:那就是快呗: 下面是AtomicInteger的使用方法: package com.example.demo.t

  • 详解Java并发包中线程池ThreadPoolExecutor

    一.线程池简介 线程池的使用主要是解决两个问题:①当执行大量异步任务的时候线程池能够提供更好的性能,在不使用线程池时候,每当需要执行异步任务的时候直接new一个线程来运行的话,线程的创建和销毁都是需要开销的.而线程池中的线程是可复用的,不需要每次执行异步任务的时候重新创建和销毁线程:②线程池提供一种资源限制和管理的手段,比如可以限制线程的个数,动态的新增线程等等. 在下面的分析中,我们可以看到,线程池使用一个Integer的原子类型变量来记录线程池状态和线程池中的线程数量,通过线程池状态来控制任

  • 求最大子数组之和的方法解析(2种可选)

    问题描述:一个有n个元素的数组,这n个元素可以是正数也可以是负数,求最大子数组的和. 方法1:蛮力法 思路:最简单也是最容易想到的方法就是找出所有子数组,然后求所有子数组的和,在所有子数组的和中取最大值. /** * 方法1(蛮力法):两次循环求最大子数组之和 */ public static int maxSubArray1(int[] a){ int i,j; int ThisSum=0; int MaxSum=0; for (i = 0; i < a.length; i++) { This

  • java并发编程_线程池的使用方法(详解)

    一.任务和执行策略之间的隐性耦合 Executor可以将任务的提交和任务的执行策略解耦 只有任务是同类型的且执行时间差别不大,才能发挥最大性能,否则,如将一些耗时长的任务和耗时短的任务放在一个线程池,除非线程池很大,否则会造成死锁等问题 1.线程饥饿死锁 类似于:将两个任务提交给一个单线程池,且两个任务之间相互依赖,一个任务等待另一个任务,则会发生死锁:表现为池不够 定义:某个任务必须等待池中其他任务的运行结果,有可能发生饥饿死锁 2.线程池大小 注意:线程池的大小还受其他的限制,如其他资源池:

  • java多线程编程学习(线程间通信)

    一.概要 线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就是成为整体的必用方案之一.可以说,使线程进行通信后,系统之间的交互性会更强大,在大大提高cpu利用率的同时还会使程序员对各线程任务在处理过程中进行有效的把控和监督. 二.等待/通知机制 1."wait/notify"机制:等待/通知机制,wait使线程暂停运行,而notify 使暂停的线程继续运行.用一个厨师和服务员的交互来说明: (1) 服务员取到菜的时间取决于厨师,所以服务员就有&

  • Java 并发编程之线程挂起、恢复与终止

    挂起和恢复线程 Thread 的API中包含两个被淘汰的方法,它们用于临时挂起和重启某个线程,这些方法已经被淘汰,因为它们是不安全的,不稳定的.如果在不合适的时候挂起线程(比如,锁定共享资源时),此时便可能会发生死锁条件--其他线程在等待该线程释放锁,但该线程却被挂起了,便会发生死锁.另外,在长时间计算期间挂起线程也可能导致问题. 下面的代码演示了通过休眠来延缓运行,模拟长时间运行的情况,使线程更可能在不适当的时候被挂起: public class DeprecatedSuspendResume

  • Java为什么使用补码进行计算的原因分析

    我们主要要解决的问题就是负数的表示,而众所周知,绝对值相等的两个正负数之和为0. 假设我们有正数 0000 0000 0000 1111,我们如何表示其相反数呢?一般我们的思路是,找一个数,跟它相加的结果等于0,但是我们发现,要找出一个与它相加后结果等于0的数还是要略加思考一下的(因为要计算进位),所以,为何不找出一个与它相加后结果是1111 1111 1111 1111的数,然后该数+1即是我们所要的答案啦. 于是,很容易的, 0000 0000 0000 1111 + 1111 1111 1

  • java多线程CountDownLatch与线程池ThreadPoolExecutor/ExecutorService案例

    1.CountDownLatch: 一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行. 2.ThreadPoolExecutor/ExecutorService: 线程池,使用线程池可以复用线程,降低频繁创建线程造成的性能消耗,同时对线程的创建.启动.停止.销毁等操作更简便. 3.使用场景举例: 年末公司组织团建,要求每一位员工周六上午8点到公司门口集合,统一乘坐公司所租大巴前往目的地. 在这个案例中,公司作为主线程,员工作为子线程. 4.代码示例: package

随机推荐