Java使用5个线程计算数组之和
作者:安迪爸爸 发布时间:2022-07-25 21:41:37
目录
前言
代码一:
代码二:
方式一:
方式二:
方式三:
总结
前言
之前写过多线程累加计数,原理跟本篇类似,传送门
累加计数比计算数组之和逻辑稍微简单一点,如果对于这块不熟悉的,可以先看下累加计数。
基本思想已经在之前那篇文章里写过了,这里就直接贴代码了。
这里分别通过自己创建线程来实现功能,还有通过线程池来实现功能。思想都差不多。只是代码写法略有不同。仅供参考。
代码一:
五个线程交替累加计算数组之和,这种方法其实不如单线程直接累加快,因为交替累加需要前一个线程计算的结果。
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方法,输出结果到控制台。
来源:https://blog.csdn.net/wzmde007/article/details/89947481
猜你喜欢
- 本文实例讲述了WinForm中实现picturebox自适应图片大小的方法。分享给大家供大家参考,具体如下:picturebox控件共有两种
- 前言该篇文章主要总结的是自己平时工作中使用频率比较高的Xml文档操作的一些常用方法和收集网上写的比较好的一些通用Xml文档操作的方法(主要包
- 1. Limit实现分页1.1 为什么需要分页 减少数据的处理量1.2 使用Limit实现分页select * from user limi
- 本文为大家分享了一个满足在线网页交流需求的实例,由于java Socket实现的网页版在线聊天功能,供大家参考,具体内容如下实现步骤:1、使
- 本文实例讲述了.net的序列化与反序列化的实现方法。分享给大家供大家参考。具体方法如下:1.序列化与反序列化概述C#中如果需要:将一个结构很
- 目录MVC结构简介SpringMVC简介SpringMVC执行流程常用注解1. @Controller2. @ResponseBody3.
- 今天想说的就是能够在我们操作数据库的时候更简单的更高效的实现,现成的CRUD接口直接调用,方便快捷,不用再写复杂的sql,带吗简单易懂,话不
- 本文实例讲述了退出Android程序时清除所有activity的方法。分享给大家供大家参考,具体如下:在一个项目中,要退出android程序
- 在 Java 中,当我们处理String时,有时需要将字符串编码为特定字符集。编码是一种将数据从一种格式转换为另一种格式的方法。字符串对象使
- 概述公司的spring boot项目不是使用默认的logback作为日志框架,而是log4j2, 主要原因是logback出现过一个生产问题
- 前言HTML5 WebSocket实现了服务器与浏览器的双向通讯,双向通讯使服务器消息推送开发更加简单,最常见的就是即时通讯和对信息实时性要
- G将军有一支训练有素的军队,这个军队除开G将军外,每名士兵都有一个直接上级(可能是其他士兵,也可能是G将军)。现在G将军将接受一个特别的任务
- 在之前项目中有用到关于获取手机联系人的部分,闲置就想和大家分享一下,话不多说,上代码:java部分:package com.example.
- int n;int &m = n;在C++中,多了一个C语言没有的引用声明符&,如上,m就是n的引用,简单的说m就是n的别名
- 一、Kotlin 调用 Java1. kotlin 关键字转义java 中的方法或变量 是 kotlin 的关键字时,使用反引号 `` 对关
- 本文实例讲述了C# Winform实现捕获窗体最小化、最大化、关闭按钮事件的方法,主要是通过重写WndProc来实现的。分享给大家供大家参考
- 今天用NewtonSoft.JSon解析一个天气数据,数据格式如:{"status":1,"detail&qu
- 任意位置获取HttpServletRequest对象方法一//获取RequestAttributes RequestAttributes r
- 前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成
- 本文实例讲述了JAVA中的final关键字用法。分享给大家供大家参考,具体如下:根据上下文环境,java的关键字final也存在着细微的区别