Java 多线程加法求和

news2024/11/16 13:41:11

Java 多线程加法求和

代码

先上代码再上解析:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class Sum implements Runnable {
    private final int[] numbers;
    private final int start;
    private final int end;
    private final AtomicInteger total;

    public Sum(int[] numbers, int start, int end, AtomicInteger total) {
        this.numbers = numbers;
        this.start = start;
        this.end = end;
        this.total = total;
    }

    @Override
    public void run() {
        int localSum = 0;
        for (int i = start; i < end; i++) {
            localSum += numbers[i];
        }
        // addAndGet 可以原子地(即线程安全地)将给定的数值增加到当前数值
        System.out.printf("local %d\n", localSum);
        total.addAndGet(localSum);
    }
}

class MultiThreadedAddition {
    public static void main(String[] args) throws InterruptedException {
        // 实现从1加到100
        int[] numbers = new int[101];
        for (int i = 1; i < numbers.length; i++) {
            numbers[i] = i;
        }

        AtomicInteger total = new AtomicInteger();
        // 假设有4个线程并发计算
        int threadCount = 4;

        // Executors.newFixedThreadPool 用于创建一个固定大小的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

        // 把 numbers.length 个(100个)任务均分给 threadCount 个(4个)线程
        int partitionSize = numbers.length / threadCount;
        for (int i = 0; i < threadCount; i++) {
            int startIndex = i * partitionSize;
            // 这里要特判一下最后一个线程的结束范围,因为可能不能恰好均分任务,比如999个任务给4个线程做...
            int endIndex = (i == threadCount - 1) ? numbers.length : (i + 1) * partitionSize;
            Sum task = new Sum(numbers, startIndex, endIndex, total);
            executorService.submit(task);
        }

        // 先关闭线程池
        executorService.shutdown();
        // 阻塞主线程,让其等待所有线程提交结果(或者直到超过最大等待时间,不过这里设置的是MAX_VALUE,就是无限等待
        executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);

        System.out.println(total.get());
    }
}

运行结果

这里是做了一个1~100的求和,我们知道结果是5050,运行检验一下:
Java 多线程 加法求和1到100

多线程的要点解析

多线程创建:Runnable Callable Thread

Runnable 接口
  1. 基本概念
    Runnable 是一个非常基础的接口,只有一个方法 void run()。任何实现了 Runnable 接口的类都可以作为一个线程的工作单元(任务)。
  2. 传递给 Thread 类的构造函数
    当一个 Runnable 实例被传给 Thread 构造函数时,可以创建一个新的线程,然后调用 Thread.start() 方法启动该线程来执行 run() 方法中的代码。
  3. 没有返回值
    Runnable 不支持返回值,并且在 run() 方法内部抛出的异常不会被捕获并转发给调用者。
Thread 类
  1. 基本概念
    Thread 是Java中用于实现线程的基础类,它实现了 Runnable 接口,所以可以通过继承 Thread 类并重写 run() 方法来创建一个可运行的线程。
  2. 接收 Runnable 实例

呼应上文

通过创建 Thread 类的子类或通过传递一个 Runnable 对象给 Thread 构造函数,可以创建和管理线程。
3. 更多 API
Thread 类提供了更多控制线程生命周期的方法,如 start()、join()、interrupt()、setName() 等。

Callable 接口
  1. 基本概念
    Callable 是在Java 1.5以后引入的,相比于 Runnable,它更加灵活。

  2. 能返回值和抛出异常
    可以通过 call() 方法返回一个结果,而且 call() 方法可以抛出受检异常(checked exception)。

3. 使用
Callable 实例不能直接启动,需要通过 ExecutorService 提交给线程池执行,并通过 Future 对象获取异步计算的结果。
使用 Callable 通常结合 FutureTask(实现了 Runnable 和 Future 接口)来包装 Callable 任务,并将其提交给线程池执行,从而可以获得线程执行的结果。

结束线程的工作

上面的代码中结束线程工作的过程中,涉及到了两个API

  • executorService.shutdown()
    相当于关闭线程池,不允许再扔新的线程或者任务进来了。
  • executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)
    如果一个线程调用这个方法,那么它就会被阻塞,暂时停止活动直到这个线程池里面的所有线程结束工作,或者等待超过指定时间——这里我们设置了 Long.MAX_VALUETimeUnit.NANOSECONDS,前者是指 无限期等待,后者是指时间单位为 纳秒

这里我们是主线程调用的,所以就是主线程被阻塞.

避免竞态

上述代码中的多线程加法求和用到了 AtomicInteger,它是 java.util.concurrent.atomic 包下原子整数类,顾名思义,它所对应整数上发生的操作都是原子性的,线程只能串行的去累加它,就能避免竞态问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1611237.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于人工智能的机动车号牌检测与推理系统v1.0

基于人工智能的机动车号牌检测与推理系统v1.0代码重构与实现。 目前整合3中现有算法&#xff0c;并完成阶段性改造&#xff0c;包括【传统方法检测车牌&#xff0c;SVM推理字符】、【YOLO方法检测车牌&#xff0c;SVM推理字符】、【YOLO方法检测车牌&#xff0c;CNN推理字符】&…

ADSP-21479的开发详解十(用CCES做Flash的编程)

硬件准备 ADSP-21479EVB开发板&#xff1a; 产品链接&#xff1a;https://item.taobao.com/item.htm?id555500952801&spma1z10.5-c.w4002-5192690539.11.151441a3Z16RLU AD-HP530ICE仿真器&#xff1a; 产品链接&#xff1a;https://item.taobao.com/item.htm?id38007…

墨子web3实时周报

蚂蚁集团Web3研发进展与布局 国内Web3赛道的领军企业——蚂蚁集团&#xff0c;凭借其在前沿科技领域的深耕不辍&#xff0c;已在Web3技术研发疆域缔造了卓越战绩。特别是在引领行业革新的关键时刻&#xff0c;集团于今年四月末震撼推出了颠覆性的Web3全套解决方案&#xff0c;…

Hive基础3

一、表的分区 大数据开发数据量较大&#xff0c;在进行数据查询计算时&#xff0c;需要对数据进行拆分&#xff0c;提升的查询速度 1-1 单个分区 单个分区是创建单个目录 -- 创建表指定分区&#xff0c;对原始数据进行分区保存 create table new_tb_user(id int,name string,ag…

通过实例学C#之序列化与反序列化XmlSerializer类

简介 可以将类序列化成xml文件&#xff0c;或者将xml文件反序列化成类对象&#xff0c;一般用于保存或加载项目参数。 构造函数 XmlSerializer() 不使用函数创建一个xmlSerializer对象。 XmlSerializer(Type type) 使用type对象创建一个xmlSerializer对象&#xff0c;注意&…

[阅读笔记23][JAM]JOINTLY TRAINING LARGE AUTOREGRESSIVE MULTIMODAL MODELS

这篇论文是24年1月发表的&#xff0c;然后是基于的RA-CM3和CM3Leon这两篇论文。它所提出的JAM结构系统地融合了现有的文本模型和图像生成模型。 主要有两点贡献&#xff0c;第一点是提出了融合两个模型的方法&#xff0c;第二点是为混合模型精心设计的指令微调策略。 下图是一个…

【Java笔记】第4章:深入学习循环结构

前言1. 循环的理解2. while循环3. do...while循环4. for循环5. 循环的控制语句6. 循环的嵌套结语 ↓ 上期回顾: 【Java笔记】第3章&#xff1a;深入学习分支结构 个人主页&#xff1a;C_GUIQU 归属专栏&#xff1a;【Java学习】 ↑ 前言 各位小伙伴大家好&#xff01;上期小编…

C语言读取数据检索存档《C语言程序设计》·第6章·用数组处理批量数据

C数组使用 添加链接描述 C语言读取数据检索存档 1 添加链接描述 2 添加链接描述 3 添加链接描述 4 添加链接描述 5 添加链接描述 6 添加链接描述 7 matlab转C 添加链接描述

19.表单输入绑定

表单输入绑定 在前端处理表单时&#xff0c;我们常常需要将表单输入框的内容同步给 JavaScript 中相应的变量。手动连接值绑定和更改事件监听器可能会很麻烦,v-model 指令帮我们简化了这一步骤 <template><input type"text" v-model"message">…

Sylar C++高性能服务器学习记录02 【日志管理-代码分析篇】

早在19年5月就在某站上看到sylar的视频了&#xff0c;一直认为这是一个非常不错的视频&#xff0c;还有幸加了sylar本人的wx&#xff0c;由于本人一直是自学编程&#xff0c;基础不扎实&#xff0c;也没有任何人的督促&#xff0c;没能坚持下去&#xff0c;每每想起倍感惋惜。恰…

部署轻量级Gitea替代GitLab进行版本控制(一)

Gitea 是一款使用 Golang 编写的可自运营的代码管理工具。 Gitea Official Website gitea: Gitea的首要目标是创建一个极易安装&#xff0c;运行非常快速&#xff0c;安装和使用体验良好的自建 Git 服务。我们采用Go作为后端语言&#xff0c;这使我们只要生成一个可执行程序即…

【EtherCAT】FMMU和SM简介

目录 一、简介 1、 FMMU 2、SM (1) 缓冲模式 (2)邮箱模式 3、FMMU将物理存储器映射到逻辑过程数据映射的配置原理 二、FMMU和SM在EtherCAT从站控制器的存储空间分配 三、FMMU和SM部分寄存器描述(LAN9253) 1、FMMU 2、SM 四、FMMU和SM的数据结构&#xff08;soem主站&…

修复vite中使用react提示Fast refresh only works when a file only exports components.

前言 我通过 vite 构建了一个 react 应用并使用 react.lazy 来懒加载组件&#xff0c;但是在使用过程中 一直提示 Fast refresh only works when a file only exports components. Move your component(s) to a separate file.eslint(react-refresh/only-export-components)。…

x-cmd ai | x openai - 用于发送 openai API 请求,以及与 ChatGPT 对话

介绍 Openai 模块是 Openai 大模型 Chatgpt 3 和 ChatGPT 4 命令行实现。x-cmd 提供了多个不同平台间多种 AI 大模型的调用能力。无论是本地模型还是 Web 服务上的模型&#xff0c;用户都可以在不同的 AI 大模型间直接无缝切换&#xff0c;并能把之前的聊天记录发送给新的大模…

第64天:服务攻防-框架安全CVE复现Apache ShiroApache Solr

目录 思维导图 案例一&#xff1a;Apache Shiro-组件框架安全 shiro反序列化 cve_2016_4437 CVE-2020-17523 CVE-2020-1957 案例二&#xff1a;Apache Solr-组件框架安全 远程命令执行 RCE&#xff08;CVE-2017-12629&#xff09; 任意文件读取 AND 命令执行&#xff08…

C++ 速成

C 概述 c 融合了3中不同的编程方式&#xff1a; C语言代表的过程性语言C 在C语言基础上添加的类代表的面向对象语言C 模板支持的泛型编程 C 标准 一种描述C 的一些语法规则的代码准则 C11 C 应用 游戏 C 效率是一个很重要的原因&#xff0c;绝大部分游戏殷勤都是C写的 网…

【刷题】 二分查找进阶

送给大家一句话&#xff1a; 你向神求助是因为相信神&#xff0c;神没有回应你是因为神相信你 ε≡٩(๑>₃<)۶ &#xfeff;ε≡٩(๑>₃<)۶ &#xfeff;ε≡٩(๑>₃<)۶ 一心向学 二分查找进阶 1 前言Leetcode 852. 山脉数组的峰顶索引题目描述算法思…

Unity类银河恶魔城学习记录13-5,6 p146 Delete save file,p147 Encryption of saved data源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili FileDataHandler.cs using System; using System.IO; using UnityEngine; p…

Git TortoiseGit 安装使用详细教程

前言 Git 是一个免费的开源分布式版本控制系统&#xff0c;是用来保存工程源代码历史状态的命令行工具&#xff0c;旨在处理从小型到非常大型的项目&#xff0c;速度快、效率高。《请查阅Git详细说明》。TortoiseGit 是 Git 的 Windows Shell 界面工具&#xff0c;基于 Tortoi…

pg内核之日志管理器(五)WAL日志

概念 WAL日志 数据库运行过程中&#xff0c;数据一般是会保存在内存和磁盘中&#xff0c;为保证数据的安全性&#xff0c;防止数据库崩溃时数据不丢失&#xff0c;一般都是要保证数据实时落盘的&#xff0c;但是又由于磁盘随机IO读写速率与内存相比慢很多&#xff0c;如果每个…