前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >8种创建Java线程的方式,你知道几个?

8种创建Java线程的方式,你知道几个?

原创
作者头像
程序员追风
修改于 2019-10-10 02:27:46
修改于 2019-10-10 02:27:46
38000
代码可运行
举报
运行总次数:0
代码可运行

作者:唐彤

前言

创建线程,是多线程编程中最基本的操作,彤哥总结了一下,大概有8种创建线程的方式,你知道吗?

1.继承Thread类并重写run()方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CreatingThread01 extends Thread {
 @Override
 public void run() {
 System.out.println(getName() + " is running");
 }
 public static void main(String[] args) {
 new CreatingThread01().start();
 new CreatingThread01().start();
 new CreatingThread01().start();
 new CreatingThread01().start();
 }
}

继承Thread类并重写run()方法,这种方式的弊端是一个类只能继承一个父类,如果这个类本身已经继承了其它类,就不能使用这种方式了。

2.实现Runnable接口

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CreatingThread02 implements Runnable {
 @Override
 public void run() {
 System.out.println(Thread.currentThread().getName() + " is running");
 }
 public static void main(String[] args) {
 new Thread(new CreatingThread02()).start();
 new Thread(new CreatingThread02()).start();
 new Thread(new CreatingThread02()).start();
 new Thread(new CreatingThread02()).start();
 }
}

实现Runnable接口,这种方式的好处是一个类可以实现多个接口,不影响其继承体系。

3.匿名内部类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CreatingThread03 {
 public static void main(String[] args) {
 // Thread匿名类,重写Thread的run()方法
 new Thread() {
 @Override
 public void run() {
 System.out.println(getName() + " is running");
 }
 }.start();
 // Runnable匿名类,实现其run()方法
 new Thread(new Runnable() {
 @Override
 public void run() {
 System.out.println(Thread.currentThread().getName() + " is running");
 }
 }).start();
 // 同上,使用lambda表达式函数式编程
 new Thread(()->{
 System.out.println(Thread.currentThread().getName() + " is running");
 }).start();
 }
}

使用匿名类的方式,一是重写Thread的run()方法,二是传入Runnable的匿名类,三是使用lambda方式,现在一般使用第三种(java8+),简单快捷。

4.实现Callabe接口

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CreatingThread04 implements Callable<Long> {
 @Override
 public Long call() throws Exception {
 Thread.sleep(2000);
 System.out.println(Thread.currentThread().getId() + " is running");
 return Thread.currentThread().getId();
 }
 public static void main(String[] args) throws ExecutionException, InterruptedException {
 FutureTask<Long> task = new FutureTask<>(new CreatingThread04());
 new Thread(task).start();
 System.out.println("等待完成任务");
 Long result = task.get();
 System.out.println("任务结果:" + result);
 }
}

实现Callabe接口,可以获取线程执行的结果,FutureTask实际上实现了Runnable接口。

5.定时器(java.util.Timer)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CreatingThread05 {
 public static void main(String[] args) {
 Timer timer = new Timer();
 // 每隔1秒执行一次
        timer.schedule(new TimerTask() {
 @Override
 public void run() {
 System.out.println(Thread.currentThread().getName() + " is running");
 }
 }, 0 , 1000);
 }
}

使用定时器java.util.Timer可以快速地实现定时任务,TimerTask实际上实现了Runnable接口。

6.线程池

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CreatingThread06 {
 public static void main(String[] args) {
 ExecutorService threadPool = Executors.newFixedThreadPool(5);
 for (int i = 0; i < 100; i++) {
            threadPool.execute(()-> System.out.println(Thread.currentThread().getName() + " is running"));
 }
 }
}

使用线程池的方式,可以复用线程,节约系统资源。

7.并行计算(Java8+)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CreatingThread07 {
 public static void main(String[] args) {
 List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
 // 串行,打印结果为12345
        list.stream().forEach(System.out::print);
 System.out.println();
 // 并行,打印结果随机,比如35214
        list.parallelStream().forEach(System.out::print);
 }
}

使用并行计算的方式,可以提高程序运行的效率,多线程并行执行。

8.Spring异步方法

首先,springboot启动类加上 @EnableAsync注解(@EnableAsync是spring支持的,这里方便举例使用springboot)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@SpringBootApplication
@EnableAsync
public class Application {
 public static void main(String[] args) {
 SpringApplication.run(Application.class, args);
 }
}

其次,方法加上 @Async注解。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Service
public class CreatingThread08Service {
 @Async
 public void call() {
 System.out.println(Thread.currentThread().getName() + " is running");
 }
}

然后,测试用例直接跟使用一般的Service方法一模一样。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class CreatingThread08Test {
 @Autowired
 private CreatingThread08Service creatingThread08Service;
 @Test
 public void test() {
        creatingThread08Service.call();
        creatingThread08Service.call();
        creatingThread08Service.call();
        creatingThread08Service.call();
 }
}

运行结果如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
task-3 is running
task-2 is running
task-1 is running
task-4 is running

可以看到每次执行方法时使用的线程都不一样。

使用Spring异步方法的方式,可以说是相当地方便,适用于前后逻辑不相关联的适合用异步调用的一些方法,比如发送短信的功能。

欢迎大家关注我的公种浩【程序员追风】,文章都会在里面更新,整理的资料也会放在里面。

总结

(1)继承Thread类并重写run()方法;

(2)实现Runnable接口;

(3)匿名内部类;

(4)实现Callabe接口;

(5)定时器(java.util.Timer);

(6)线程池;

(7)并行计算(Java8+);

(8)Spring异步方法;

福利

上面介绍了那么多创建线程的方式,其实本质上就两种,一种是继承Thread类并重写其run()方法,一种是实现Runnable接口的run()方法,那么它们之间到底有什么联系呢?

请看下面的例子,同时继承Thread并实现Runnable接口,应该输出什么呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CreatingThread09 {
 public static void main(String[] args) {
 new Thread(()-> {
 System.out.println("Runnable: " + Thread.currentThread().getName());
 }) {
 @Override
 public void run() {
 System.out.println("Thread: " + getName());
 }
 }.start();
 }
}

说到这里,我们有必要看一下Thread类的源码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Thread implements Runnable {
 // Thread维护了一个Runnable的实例
 private Runnable target;
 public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
 }
 public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
 }
 private void init(ThreadGroup g, Runnable target, String name,
 long stackSize, AccessControlContext acc,
 boolean inheritThreadLocals) {
 // ...
 // 构造方法传进来的Runnable会赋值给target
 this.target = target;
 // ...
 }
 @Override
 public void run() {
 // Thread默认的run()方法,如果target不为空,会执行target的run()方法
 if (target != null) {
            target.run();
 }
 }
}

看到这里是不是豁然开朗呢?既然上面的例子同时继承Thread并实现了Runnable接口,根据源码,实际上相当于重写了Thread的run()方法,在Thread的run()方法时实际上跟target都没有关系了。

所以,上面的例子输出结果为 Thread:Thread-0,只输出重写Thread的run()方法中的内容。

最后

欢迎大家一起交流,喜欢文章记得点个赞哟,感谢支持!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
uniapp使用WebSocket实现即时通讯
WebSocket是一种基于TCP协议的全双工通信协议,它可以在客户端和服务器之间建立一个持久性的连接,实现实时通信。在uniapp中,我们可以使用uni-socketio插件来实现WebSocket的功能。
超级小可爱
2023/10/18
4.4K0
WebSocket 基础与应用系列 —— 抓个 WebSocket 的包
在传统的 Web 中,要实现实时通信,通用的方式是采用 HTTP 协议不断发送请求,即轮询(Polling)。
程序员海军
2021/10/11
1.3K0
WebSocket 基础与应用系列 ——  抓个 WebSocket 的包
socket心跳检测
以下是一个简单的示例代码,用于在前后端之间进行基本的心跳检测。 前端代码(使用 JavaScript):
程序员王天
2023/10/18
5840
利用whistle调试WebSocket和Socket请求
whistle v1.6.0 (Github地址:https://github.com/avwo/whistle) 开始支持WebSocket和一般Socket的抓包、构造请求、以及修改发送或接收的数
IMWeb前端团队
2017/12/28
4.8K0
利用whistle调试WebSocket和Socket请求
Socket的讲解
伙伴们,如果你觉得我写的文章对你有帮助就给zayyo点一个赞👍或者关注➕都是对我最大的支持。当然你也可以加我微信:IsZhangjianhao,邀你进我的前端学习交流群,一起学习前端,成为更优秀的工程师~
zayyo
2023/11/18
2191
2万字长文肝了一个实时聊天室,只为让她学会websocket
看演示不过瘾,我也玩一下(http://socket.vjscoder.com/websocket-chatroom/index.html#/)
前端胖头鱼
2022/07/25
9930
2万字长文肝了一个实时聊天室,只为让她学会websocket
前端架构师破局技能,NodeJS 落地 WebSocket 实践
本文从网络协议,技术背景,安全和生产应用的方向,详细介绍 WebSocket 在 Node.js 中的落地实践。
杨成功
2022/03/09
1.9K0
前端架构师破局技能,NodeJS 落地 WebSocket 实践
webSocket和EventSource的区别
WebSocket和EventSource是两种在Web应用程序中用于实现实时通信的不同技术。WebSocket是一种双向通信协议,允许服务器与客户端建立持久性连接并通过该连接发送消息。而EventSource是一种服务器推送技术,只允许服务器向客户端发送消息,而不允许客户端向服务器发送消息。 在下面的描述中,我将详细介绍WebSocket和EventSource的不同之处,并提供一些代码示例。
世间万物皆对象
2024/03/20
4190
as3与node.js的socket通信
SocketManager最多在连接失败时,进行5次重连。建立socket连接代码:
meteoric
2018/11/16
1K0
Web的socket与C# socket相互通信
web端代码就是js代码,C#有两种方式:使用第三方库,如Fleck,使用C#原生socket编程实现
郑子铭
2023/08/29
2860
Web的socket与C# socket相互通信
使用 WebSocket 实现跨域 iframe 通信
本文是使用 WebSocket 实现跨域 iframe 通信思路实现了一个本地 Demo,功能有:
草帽lufei
2024/05/08
3760
使用 WebSocket 实现跨域 iframe 通信
5000字!带你零距离接触websocket!
原文 https://juejin.im/post/6876301731966713869
lucifer210
2020/10/23
5240
5000字!带你零距离接触websocket!
基于uniapp+deepseek+vue3跨平台ai流式对话
基于uniapp+vue3集成deepseek-v3实战跨端流式输出AI对话系统。支持暗黑+亮色模式、代码高亮、本地会话存储等功能。支持编译到小程序+h5+app端。
andy2018
2025/05/06
7190
基于uniapp+deepseek+vue3跨平台ai流式对话
性能测试之微信小程序websocket协议
最近复习性能测试,也想看看小程序聊天页面中的信息底层是怎么实现的,今天试着写了写。
高楼Zee
2019/12/27
1K0
性能测试之微信小程序websocket协议
1分钟创建一个实时通信应用
1. OpenAI使用GPT-4 LLM进行内容审核,警告不要有偏见,该公司希望在人类参与循环的情况下消除训练期间引入的不良偏见。
希里安
2023/10/30
2020
1分钟创建一个实时通信应用
基于 socket.io 快速实现一个实时通讯应用WebSocket概念实现用socket.io实现一个实时接收信息的例子分析webSocket协议参考文章
随着web技术的发展,使用场景和需求也越来越复杂,客户端不再满足于简单的请求得到状态的需求。实时通讯越来越多应用于各个领域。
用户2356368
2019/05/07
2.6K0
基于 socket.io 快速实现一个实时通讯应用WebSocket概念实现用socket.io实现一个实时接收信息的例子分析webSocket协议参考文章
websocket深入浅出
答: 它是一种网络通信协议,是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
全栈程序员站长
2022/09/14
2.3K0
websocket深入浅出
socket.io搭配pm2(cluster)集群解决方案
socket.io与cluster 在线上系统中,需要使用node的多进程模型,我们可以自己实现简易的基于cluster模式的socket分发模型,也可以使用比较稳定的pm2这样进程管理工具。在常规的http服务中,这套模式一切正常,可是一旦server中集成了socket.io服务就会导致ws通道建立失败,即使通过backup的polling方式仍会出现时断时连的现象,因此我们需要解决这种问题,让socket.io充分利用多核。 在这里之所以提到socket.io而未说websocket服务,是因为so
欲休
2018/03/15
6K1
socket.io搭配pm2(cluster)集群解决方案
RPC远程调用浏览器函数
早闻 RPC(Remote Procedure Call)远程过程调用,这一词了,应该是在安卓逆向的时候听闻的,当时吹嘘的意思是这样的,通过另一个远端服务器来调用安卓代码中的函数,并将执行后的结果返回。比如有一个加密算法,如果要实现脱机(脱离当前环境)运行的话,就需要扣除相对应的代码,补齐对应的环境(模块,上下文,语言),然而要在补齐该加密算法的环境可不好实现,而通过 RPC 则可以免除扣代码,通过数据通信来达到远程调用的目的,听起来是挺牛逼的,实际上也确实挺骚的。这里我将以浏览器与本地搭建一个 websocket 来实现调用浏览器内的函数。
愧怍
2022/12/27
1.1K0
RPC远程调用浏览器函数
基于 socket.io 快速实现一个实时通讯应用
随着web技术的发展,使用场景和需求也越来越复杂,客户端不再满足于简单的请求得到状态的需求。实时通讯越来越多应用于各个领域。
用户2356368
2022/04/07
1.7K0
基于 socket.io 快速实现一个实时通讯应用
相关推荐
uniapp使用WebSocket实现即时通讯
更多 >
LV.4
这个人很懒,什么都没有留下~
目录
  • 前言
  • 1.继承Thread类并重写run()方法
  • 2.实现Runnable接口
  • 3.匿名内部类
  • 4.实现Callabe接口
  • 5.定时器(java.util.Timer)
  • 6.线程池
  • 7.并行计算(Java8+)
  • 8.Spring异步方法
  • 总结
  • 福利
  • 最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档