【Java】线程使用方式
(1)继承 Tread 类
- 继承
Thread类,创建一个新的线程类 - 重写
run()方法,将需要并发执行的业务代码编写在run()方法中
//继承Thread来创建一个线程类
class MyThread extends Thread{@Overridepublic void run(){System.out.println("hello Thread");}public static void main(String[] args) {Thread t=new MyThread();//调用start方法启动线程t.start();}
}
(2)实现 Runnable 接口
将需要异步执行的业务逻辑代码写在Runnable实现类的run()方法中,再将Runnable实例作为target执行目标传入Thread实例,其完整步骤如下:
- 定义一个新类实现
Runnable接口 - 实现
Runnable接口中的run()抽象方法,将线程代码逻辑写在该run()实现方法中 - 通过
Thread类创建线程对象,将Runnable实例作为实际参数传递给Thread类的构造器,由Thread构造器将该Runnable实例赋值给自己的target执行目标属性 - 调用
Thread实例的start()方法启动线程 - 线程启动之后,线程的
run()方法将被JVM执行,该run()方法将调用target属性的run()方法,从而完成Runnable实现类中业务代码逻辑的并发执行
//实现Runnable接口。
class MyRunnable implements Runnable{@Overridepublic void run(){System.out.println("hello Thread");}public static void main(String[] args) {Thread t=new Thread(new MyRunnable());t.start();}
}
缺点
- 创建的类不是线程类,而是线程的
target执行目标类,需要将其实例作为参数传入线程类的构造器,才能创建真正的线程 - 访问当前线程的属性,不能直接访问
Thread的实例方法,必须通过Thread.currentThread()获取当前线程实例
优点
- 可以避免由于Java单继承带来的局限性。如果异步逻辑所在类已经继承了一个基类,就没有办法再继承
Thread类。比如,当一个Dog类继承了Pet类,再要继承Thread类就不行了。所以在已经存在继承关系的情况下,只能使用实现Runnable接口的方式。 - 逻辑和数据更好分离。通过实现
Runnable接口的方法创建多线程更加适合同一个资源被多段业务逻辑并行处理的场景。在同一个资源被多个线程逻辑异步、并行处理的场景中,通过实现Runnable接口的方式设计多个target执行目标类可以更加方便、清晰地将执行逻辑和数据存储分离,更好地体现了面向对象的设计思想。
继承Thread和实现Runnable区别
- 继承
Thread类用于多个线程并发完成各自的任务,访问各自的数据资源 - 实现
Runnable接口用于多个线程并发完成同一个任务,访问同一份数据资源,数据共享资源需要使用原子类型或者进行线程同步控制
(3)实现 Callable 接口:带有返回值
使用Callable和FutureTask创建线程的步骤如下:
- 创建一个
Callable接口的实现类,并实现其call()方法,编写异步执行的具体逻辑,可以有返回值 - 使用
Callable实现类的实例构造一个FutureTask实例 - 使用
FutrueTask实例作为Thread构造器的target入参,构造新的Thread线程实例 - 调用
Thread实例的start()方法启动线程,启动新线程的run()方法并发执行 - 调用
FutureTask对象的get()方法阻塞性地获取并发线程执行结果
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;public class UseCallable implements Callable<Integer> {@Override//call方法可以抛异常,像线程里面的run方法最多只能在run方法内trycatchpublic Integer call() throws Exception {//所需要实现的功能代码System.out.print("hello Thread");return 1;}public static void main(String[] args) {UseCallable useCallable = new UseCallable();FutureTask<Integer> futureTask = new FutureTask<>(useCallable);new Thread(futureTask).start();try {System.out.print(futureTask.get());}catch(Exception e){}}
}
Callable与Runnable区别
Runnable的唯一抽象方法run()没有返回值,也没受检查异常的异常声明,Callable接口的call()有返回值,并且声明了受检查异常,功能更强- 使用
Runnable创建多线程,实现Runnable接口的实例作为Thread线程实例的target来使用 - 使用
Callable创建多线程,使用RunnableFuture作为Thread线程实例的target实例和获取异步执行的结果,其实现类是FutureTask
(4)线程池创建线程
前面几种方法创建的Thread实例在执行完成之后是不可复用的,实际工作中需要对已创建好的线程实例进行复用,需要用到线程池。
ExecutorService是Java提供的一个线程池接口,每次在异步执行target目标任务的时候,可以通过ExecutorService线程池实例去提交或者执行。ExecutorService实例负责对池中的线程进行管理和调度,并且可以有效控制最大并发线程数,提高系统资源的使用率,同时提供定时执行、定频执行、单线程、并发数控制等功能。
import java.util.concurrent.*;public class MultiThread {private static final int MAX_TURN = 5;private static final int COMPUTE_TIMES = 100000000;private static ExecutorService pool = Executors.newFixedThreadPool(3);static class RunnableTask implements Runnable {@Overridepublic void run() {for (int i = 0; i < MAX_TURN; i++) {System.out.println("多线程执行,第:" + i + "次执行");}}}static class CallableTask implements Callable<Long> {@Overridepublic Long call() throws Exception {long startTime = System.currentTimeMillis();System.out.println("多线程执行,开始时间为:" + startTime);Thread.sleep(1000);for (int i = 0; i < COMPUTE_TIMES; i++) {int j = i * 10000;}long endTime = System.currentTimeMillis();long used = endTime - startTime;System.out.println("多线程执行结束,用时:" + used);return used;}}public static void main(String[] args) throws ExecutionException, InterruptedException {pool.execute(new RunnableTask());pool.execute(new Runnable() {@Overridepublic void run() {for (int i = 0; i < MAX_TURN; i++) {System.out.println("多线程执行,直接实现Runnable");}}});Future<Long> future = pool.submit(new CallableTask());Long result = future.get();System.out.println("异步执行多线程结果为:" + result);}
}
注意:实际开发中不会使用Executors创建线程池,而是使用ThreadPoolExecutor的构造方法
execute()与submit()区别
接收的参数不一样
submit()可以接收两种入参:无返回值的Runnable类型的target执行目标实例和有返回值的Callable类型的target执行目标实例;
execute()只接收无返回值的target执行目标实例或者无返回值的Thread实例。
submit()有返回值,execute()没有返回值
submit()方法在提交异步target执行目标之后会返回Future异步任务实例,以便对target的异步执行过程进行控制,比如取消执行、获取结果等。
execute()没有任何返回,target执行目标实例在执行之后没有办法对其异步执行过程进行控制,只能任其执行,直到其执行结束。
相关文章:
【Java】线程使用方式
(1)继承 Tread 类 继承Thread类,创建一个新的线程类重写run()方法,将需要并发执行的业务代码编写在run()方法中 //继承Thread来创建一个线程类 class MyThread extends Thread{Overridepublic void run(){System.out.println("hello Thread"…...
零基础想转行学习Python,该如何学习,有学习路线分享吗?(2023年给初学者的建议)
Python属于一种面向对象、解释性的高级语言,它如今在众多领域都被应用,包括操作系统管理、Web开发、服务器运维的自动化脚本、科学计算、桌面软件、服务器软件(网络软件)、游戏等方面,且Python在今后将被大规模地应用到大数据和人工智能方面。…...
IDEA Maven install Failed to execute goal org.apache.maven.plugins异常处理
目录一、异常错误二、原因三、解决方法修改pom.xml资源配置文件一、异常错误 由于服务器编译拦截了静态资源,导致出现异常,需要重新打包编译 打开IDEA带的Maven管理,双击clean清除由项目编译创建的target 再双击install安装jar包到本地仓库…...
TensorFlow-Keras - FM、WideAndDeep、DeepFM、DeepFwFM、DeepFmFM 理论与实战
目录 一.引言 二.浅层模型概述 1.LR 2.FM 3.FMM 4.FwFM 5.FmFM 三.常用推荐算法实现 Pre.数据准备 1.FM 2.WideAndDeep 3.DeepFM 4.DeepFwFM 5.DeepFmFM 四.总结 1.函数测试 2.函数效果与复杂度对比[来自FmFM论文] 3.More 一.引言 推荐系统中常见的 CTR 模型…...
Java浅析电信数据采集
技术:Java等摘要:电信运营系统中,电信计费系统是主要的支撑系统,占有重要地位。对于电信计费系统是电信运营商的核心竞争力之一这一观点愈来愈被业界认同。电信计费系统中的数据蕴含着企业经营态势、客户群分布特征及消费习惯、各…...
那些开发中需要遵守的产研开发规范
入职新公司第三天,没干啥其他活,基本在阅读产研开发规范。公司在技术方面沿用的是阿里的一套技术,所以入职之前需要先阅读《阿里巴巴开发规范》。今天整理一些平时需要关注的阿里规约和数据库开发规范,方便今后在开发过程中查阅。…...
一文深入分析-内核并发消杀器(KCSAN)
一、KCSAN介绍 KCSAN(Kernel Concurrency Sanitizer)是一种动态竞态检测器,它依赖于编译时插装,并使用基于观察点的采样方法来检测竞态,其主要目的是检测数据竞争。 KCSAN是一种检测LKMM(Linux内核内存一致性模型)定义的数据竞争(data race…...
Java学习-IO流-字符缓冲流
Java学习-IO流-字符缓冲流 字符缓冲流↙ ↘ BufferedReader BufferedWtrier 字符缓冲输入流 字符缓冲输出流底层自带长度为8192的缓冲区提高性能 public BufferedReader(Reader r):把基本流包装成高级流 public BufferedWtrier(Wtrier w):把…...
Java的一维数组遍历、求最值、冒泡排序
一.数组遍历: Example: import java.util.ArrayList; public class App { public static void main(String[] args) { int[]arr{1,2,3,4,5}; for(int i0;i<arr.length;i){ System.out.println(arr[i]); } } 运行结果:12345 定义了一…...
Free for photo container detection, container damage detect PaaS
集装箱箱号识别API免费,飞瞳引擎集装箱人工智能平台,可通过API二次开发或小程序拍照使用,可二次开发应用码头港区海关仓库口岸铁路场站船公司堆场,实现云端集装箱信息识别/集装箱箱况残损检测/好坏箱检验,高检测率/高实…...
【golang】【源代码】reflect.DeepEqual(x,y)函数
reflect.DeepEqual(x, y)函数 功能是比较x和y是否一致,x和y不仅限于基础类型,也可以是像array、 slice、 map、 ptr、struct、interface类型,在代码中经常能见到。 一起看下是怎么实现的吧~ func DeepEqual(x, y interface{}) bool {if x …...
Python实现定时执行脚本(4)
前言 本文是该专栏的第16篇,后面会持续分享python的各种干货知识,值得关注。 在项目开发中,难免会需要用到定时任务。比如说,在某个时间段,甚至是达到某时某分某秒自动运行你部署好的功能脚本。而在本专栏的前面,笔者有详细介绍过3种使用python执行定时脚本的方法。 1.…...
量子力学(4) 全同粒子
如果势能与时间无关,那么Ψψe−iEt/ℏ\Psi\psi e^{-iEt/\hbar}Ψψe−iEt/ℏ,EEE是系统的总能量。 全同粒子分为玻色子和费米子。所有电子是全同的费米子。所有质子是全同的费米子。全同就是说不可能区分出其中的一个,比如说你摇了五个骰子…...
13、Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
简介 主页:https://github. com/microsoft/Swin-Transformer. Swin Transformer 是 2021 ICCV最佳论文,屠榜了各大CV任务,性能优于DeiT、ViT和EfficientNet等主干网络,已经替代经典的CNN架构,成为了计算机视觉领域通用…...
C++基础入门丨8. 结构体——还需要知道这些
Author:AXYZdong 硕士在读 工科男 有一点思考,有一点想法,有一点理性! 定个小小目标,努力成为习惯!在最美的年华遇见更好的自己! CSDNAXYZdong,CSDN首发,AXYZdong原创 唯…...
算法第十六期——动态规划(DP)之线性DP
【概述】 线性动态规划,是较常见的一类动态规划问题,其是在线性结构上进行状态转移,这类问题不像背包问题、区间DP等有固定的模板。 线性动态规划的目标函数为特定变量的线性函数,约束是这些变量的线性不等式或等式,目…...
智慧新零售网络解决方案,助力新零售企业数智化转型
随着数字化时代的不断发展,新零售连锁业务模式“线上线下”融合发展,数据、设备在逐渐增加,门店数量也会随着企业规模的扩大而增加,但由于传统网络架构不稳定、延时、容量小影响服务质量(QoS)、分支设备数量…...
Go语言规范中的可赋值
了解可赋值规范的重要性当使用type关键字定义类型的时候,会遇到一些问题,如下:func main(){var i int 2pushInt(i) } type MyInt int //基于int定义MyInt func pushInt(i MyInt){}结果:调用函数pushInt报错 cannot use i (variab…...
外盘国际期货招商:原油市场热点话题
原油市场热点话题 问:目前美国原油库存如何? 答:EIA原油库存数据显示,由于美国炼油厂季节性检修,开工率继续下降,原油库存连续九周增长至2021年5月份以来最高水平,同期美国汽油库存减少而精炼…...
[蓝桥杯 2018 省 A] 付账问题 贪心题
几个人一起出去吃饭是常有的事。但在结帐的时候,常常会出现一些争执。现在有 n 个人出去吃饭,他们总共消费了 S 元。其中第 i 个人带了 ai 元。幸运的是,所有人带的钱的总数是足够付账的,但现在问题来了:每个人分别要出…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
