Java 多线程实现1到1千万的求和操作

news/2024/11/16 19:25:48/

一、使用多线程的背景

  1. 提高程序速度和响应性:许多应用程序需要同时执行多个任务,例如网络服务器,图形图像处理,模拟程序等。使用多线程可以让程序同时执行多个部分,从而显著提高程序的执行速度、响应速度。

  2. 充分利用 CPU:在单核 CPU 的情况下,只有一个线程能够使用 CPU 进行计算。但随着 CPU 的多核化,可以同时开启多个线程,从而充分利用 CPU 资源。

  3. 方便协作编程:多线程编程可以让不同的开发者同时负责程序不同部分的开发工作,从而达成快速开发的目标。

  4. 提供更好的用户体验:对于复杂的应用程序,使用多线程可以让用户更好的体验程序的交互响应。

        总之,使用多线程能够将程序的执行与资源利用分离,使得代码更具可维护性、模块化,同时改善程序的执行效率和用户体验。

二、创建多线程的常见的几种方法(介绍两种常用的)

方式一、通过继承 Thread 类创建线程

public class Thread01 {public static void main(String[] args) throws InterruptedException {//创建 Cat 对象,可以当做线程使用Cat cat = new Cat();/*(1)public synchronized void start() {start0();}(2)//start0() 是本地方法,是 JVM 调用, 底层是 c/c++实现//真正实现多线程的效果, 是 start0(), 而不是 runprivate native void start0();*/cat.start();//启动线程-> 最终会执行 cat 的 run 方法//cat.run();//run 方法就是一个普通的方法, 没有真正的启动一个线程,就会把 run 方法执行完毕,才向下执行//说明: 当 main 线程启动一个子线程 Thread-0, 主线程不会阻塞, 会继续执行//这时 主线程和子线程是交替执行.. System.out.println("主线程继续执行" + Thread.currentThread().getName());//名字 mainfor(int i = 0; i < 60; i++) {System.out.println("主线程 i=" + i);//让主线程休眠Thread.sleep(1000);}}}//1. 当一个类继承了 Thread 类, 该类就可以当做线程使用//2. 我们会重写 run 方法,写上自己的业务代码//3. run Thread 类 实现了 Runnable 接口的 run 方法/*@Overridepublic void run() {if (target != null) {target.run();}}*/class Cat extends Thread {int times = 0;@Overridepublic void run() {//重写 run 方法,写上自己的业务逻辑//当 times 到 80, 退出 while, 这时线程也就退出.. }do {//该线程每隔 1 秒。在控制台输出 “喵喵, 我是小猫咪”System.out.println("喵喵, 我是小猫咪" + (++times) + " 线程名=" + Thread.currentThread().getName());//让该线程休眠 1 秒 ctrl+alt+ttry {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}} while (times != 80);}
}

 方式二、通过实现 Runnable 接口创建线程

        由于Java是单继承的,某些情况下一个类可能已经继承了某个父类,这时在用继承Thread类方法来创建线程显然不可能了。此时就可以通过实现Runnable接口来创建线程。

这里实现了用Runnable接口来创建线程并且在主线程中实现了两个子线程。

public class Thread01 {public static void main(String[] args) {//main 线程启动两个子线程Dog dog = new Dog();//dog.start(); 这里不能调用 start//创建了 Thread 对象,把 dog 对象(实现 Runnable),放入 ThreadThread thread = new Thread(dog);thread.start();//启动第 1 个线程Tiger tiger = new Tiger();//实现了 RunnableThreadProxy threadProxy = new ThreadProxy(tiger);threadProxy.start();//启动第 2 个线程}
}class Animal {}class Tiger extends Animal implements Runnable {int count = 0;@Overridepublic void run() { //普通方法do {System.out.println("老虎嗷嗷叫..hi" + (++count) +"线程名是:"+ Thread.currentThread().getName());//休眠 1 秒try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}} while (count != 5);}}//线程代理类 , 模拟了一个极简的 Thread 类class ThreadProxy implements Runnable {//你可以把 Proxy 类当做 ThreadProxyprivate Runnable target = null;//属性,类型是 Runnable@Overridepublic void run() {if (target != null) {target.run();//动态绑定(运行类型 Tiger)}}public ThreadProxy(Runnable target) {this.target = target;}public void start() {start0();//这个方法时真正实现多线程方法}public void start0() {run();}}class Dog extends Animal implements Runnable { //通过实现 Runnable 接口,开发线程int count = 0;@Overridepublic void run() { //普通方法do {System.out.println("小狗汪汪叫..hi" + (++count) + "线程名是:"+ Thread.currentThread().getName());//休眠 1 秒try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}} while (count != 10);}}

 

Thread 和 Runnable 接口的区别:

 1. Thread 是一个类,Runnable 是接口,在 Java 语言里面的继承特性,接口可以支持多继承,而类只能单一继承。 所以如果在已经存在继承关系的类里面要实现线程的话,只能实现 Runnable 接口。

2. Runnable 表示一个线程的顶级接口,Thread 类其实是实现了 Runnable 这个接 口,我们在使用的时候都需要实现 run 方法。

3. 站在面向对象的思想来说,Runnable 相当于一个任务,而 Thread 才是真正处理的线程,所以我们只需要用 Runnable 去定义一个具体的任务,然后交给 Thread 去处理就可以了,这样达到了松耦合的设计目的。

4. 接口表示一种规范或者标准,而实现类表示对这个规范或者标准的实现,所以站在 线程的角度来说,Thread 才是真正意义上的线程实现。 Runnable 表示线程要执行的任务,因此在线程池里面,提交一个任务传递的类型是 Runnable。

总的来说,Thread 只是实现了 Runnable 接口并做了扩展,所以这两者并没什么可比性。

三、多线程实现1到1千万的求和操作

         该程序首先将1到1千万的数字平均分配给指定数量的线程进行求和,每个线程负责求和一部分数字。 每个线程求和完毕后,将结果发送到主线程中进行合并,最终得到总的求和结果。

public class SumMultiThread {private static final int MAX_NUM = 10000000;  // 求和的最大数值private static final int NUM_THREADS = 1000;  // 使用的线程数量public static void main(String[] args) {long start = System.currentTimeMillis();// 创建多个求和线程,并启动它们List<SumThread> threads = new ArrayList<>();for (int i = 0; i < NUM_THREADS; i++) {SumThread thread = new SumThread(i * (MAX_NUM / NUM_THREADS) + 1, (i + 1) * (MAX_NUM / NUM_THREADS));threads.add(thread);thread.start();}// 等待所有线程执行完毕for (SumThread thread : threads) {try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}}// 合并所有线程的结果long sum = 0;for (SumThread thread : threads) {sum += thread.getSum();}long end = System.currentTimeMillis();System.out.println("Sum of 1 to " + MAX_NUM + " is " + sum + ", runtime is " + (end - start) + "ms");}static class SumThread extends Thread {private final int from;private final int to;private long sum;public SumThread(int from, int to) {this.from = from;this.to = to;}@Overridepublic void run() {for (int i = from; i <= to; i++) {sum += i;}}public long getSum() {return sum;}}
}

四、使用多线程可能遇到的问题

        由于CPU、内存、I/O 设备速度有极大差异,为了合理利用 CPU 的高性能,平衡这三者的速度差异,计算机体系结构、操作系统、编译程序都做出了升级,但也随之出现了一些问题。主要体现为:

  • CPU 增加了缓存,以均衡与内存的速度差异;(导致 可见性问题)
  • 操作系统增加了进程、线程,以分时复用 CPU,进而均衡 CPU 与 I/O 设备的速度差异;(导致 原子性问题)
  • 编译程序优化指令执行次序,使得缓存能够得到更加合理地利用。( 导致 有序性问题)
  • 同时多线程的效率跟硬件有关,并不是开的线程越多越好。

以上一个 “1到一千万” 的求和为例,时间计算结果如下:

 

 

  


http://www.ppmy.cn/news/122669.html

相关文章

在微型计算机机箱的面板上,【简评】全侧透快拆设计,迎广101机箱体验

迎广&#xff0c;可以说是机箱产品中的一个贵族品牌&#xff0c;价格往往也比一般品牌的更高。虽然价格高&#xff0c;但是迎广的机箱不论是做工还是设计都能给人眼前一亮的感觉。比如在今年的Computex展会上&#xff0c;迎广推出的806竹质机箱让人眼前一亮&#xff0c;更是让众…

探访世优科技数字人虚拟直播产品体系 | 世优开放日再次成功举行

2023年5月30日&#xff0c;世优科技全栈技术产品体验活动&#xff08;第二期&#xff09;顺利落下帷幕。此次活动共邀请到30余位各行各业的嘉宾到场&#xff0c;在两个多小时的开放日活动中&#xff0c;世优科技全面展示数字人及虚拟直播领域的技术产品体系。来访嘉宾们全程体验…

统计软件与数据分析Lesson17----利用pytorch构建LSTM预测股票收益率详细教程

利用pytorch构建LSTM预测股票收益率详细教程 1. 整体实现思路2.代码编写2.1 step1:导入所需的库2.2 step2: 读取数据、构建训练样本2.3 step3: 定义部分辅助函数2.4 step4:LSTM模型构建2.5 step5:模型训练2.6 step6:模型预测和评估 3. 小结 1. 整体实现思路 step1:导入所需的库…

【Unity100个实用小技巧】屏幕后处理实现渐隐渐现

☀️博客主页&#xff1a;CSDN博客主页&#x1f4a8;本文由 我是小狼君 原创&#xff0c;首发于 CSDN&#x1f4a2;&#x1f525;学习专栏推荐&#xff1a;面试汇总❗️游戏框架专栏推荐&#xff1a;游戏实用框架专栏⛅️点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd;&#xf…

【Linux 】scp命令

前言 Linux scp 命令用于 Linux 之间复制文件和目录。 scp 是 secure copy 的缩写, scp 是 linux 系统下基于 ssh 登陆进行安全的远程文件拷贝命令。 scp 是加密的&#xff0c;rcp 是不加密的&#xff0c;scp 是 rcp 的加强版。 scp命令 前言一、示例1. 从本地复制到远程2. 从…

ZKTeco/熵基科技F18指纹门禁考勤一体机 破解管理员

取下螺丝&#xff0c;断电重启&#xff08;电源线一般为一红一白两根组成&#xff09;。待机器重启进入菜单页面后&#xff0c;连续按3次机器背后防拆按钮&#xff0c;等待30~50秒后&#xff0c;按“M/ok”键直接进入管理员主菜单。

前后端完全开源免费商用小区物联网平台(门禁+车辆道闸+考勤机)

真正的大师,永远都怀着一颗学徒的心&#xff01; 一、项目简介 前后端完全开源并免费商用的小区物联网平台,springbootvueelementui 二、实现功能 支持门禁车辆道闸考勤机 支持门禁管理 支持人脸识别 支持门禁协议 支持道闸设备 支持考勤管理 支持设置小区 三、技术选…

如何将华为NFC手机模拟成实体门禁卡、考勤卡

华为NFC手机模拟成实体门禁卡、考勤卡&#xff0c;即可实现手机刷卡考勤、门禁等功能&#xff0c;那么如何实现华为NFC手机模拟成实体门禁卡呢&#xff0c;下面将介绍如何模拟才能走NFC考勤机、消费机&#xff0c;远程NFC刷卡机上刷卡。 1、点开华为手机的设置界面&#xff0c…