Java三种多线程实现方式对比与优缺点分析
时间:2026-08-15 | 作者:云端旅人 | 阅读:0多线程的三种实现方式与区别
多线程的实现方式有三种,其中Runnable接口和Callable接口实现多线程的方式基本相同,主要区别就是Callable接口中的方法有返回值,并且可以声明抛出异常。
那么通过继承Thread类和其他两种接口实现多线程的方式有什么区别呢?接下来通过一个应用场景来分析说明。
售票场景分析
不妨这样理解:售票厅里一共有四个窗口,同时对外发售某日某次列车的100张车票。
这100张车票就属于典型的共享资源,而这四个售票窗口,则可以对应看成四个线程。
为了把每个窗口的售票情况展示得更清楚,可以先通过Thread的currentThread()方法拿到当前线程的实例对象,再调用getName()方法获取线程名称。
接下来,就通过继承Thread类的方式来实现多线程,具体如文件1所示。
文件1 Example04.ja va
1 // 1、定义一个继承Thread线程类的子类
2 class TicketWindow extends Thread {
3 private int tickets = 100;
4 public void run() {
5 while (true) {
6 if (tickets > 0) {
7 System.out.println(Thread.currentThread().getName()
8 + " 正在发售第 " + tickets-- + " 张票 ");
9 }
10 }
11 }
12 }
13 public class Example04 {
14 public static void main(String[] args) {
15 // 分别创建4个线程对象TicketWindow并开启,来模拟4个售票窗口
16 new TicketWindow().start();
17 new TicketWindow().start();
18 new TicketWindow().start();
19 new TicketWindow().start();
20 }
21 }
运行结果如图1所示。
图1 运行结果
继承Thread类存在的问题
从图1不难看出,同一张票实际上被卖了四遍。
问题就出在资源没有共享上:这四个线程拿的并不是同一份100张票,而是各自带着100张票在卖。
程序里一共创建了四个TicketWindow对象,这就相当于同时启用了四套彼此独立的售票逻辑。
而且每个TicketWindow对象内部都维护着一个tickets票据变量。这样一来,线程执行任务时处理的都是各自那份资源,自然不会去共同操作同一个售票资源。
小提示
文件1中创建并启动4个线程时并没有指定线程的名称,但运行结果却显示有Thread-0、Thread-1...这样的线程名称。
这是因为,在创建多线程时如果没有通过构造方法指定线程名称,则系统默认生成线程名称。
为什么更适合使用Runnable接口
由于现实中,售票系统中的票资源是共享的,因此上面的运行结果显然不合理。
为了保证售票资源共享,在程序中只能创建一个售票对象,然后开启多个线程去共享同一个售票对象来执行售票方法。
简单来说就是四个线程运行同一个售票程序,这时就需要通过实现Runnable接口的方式来实现多线程。
接下来将文件1进行修改,并使用构造方法Thread(Runnable target, String name)在创建线程对象的同时指定线程的名称,如文件2所示。
文件2 Example05.ja va
1 // 定义一个实现Runnable接口的实现类
2 class TicketWindow2 implements Runnable {
3 private int tickets = 100;
4 public void run() {
5 while (true) {
6 if (tickets > 0) {
7 System.out.println(Thread.currentThread().getName()
8 + " 正在发售第 " + tickets-- + " 张票 ");
9 }
10 }
11 }
12 }
13 public class Example05 {
14 public static void main(String[] args) {
15 // 创建TicketWindow实例对象tw
16 TicketWindow2 tw = new TicketWindow2();
17 // 分别创建4个线程对象同时进行命名,并开启线程
18 new Thread(tw, "窗口1").start();
19 new Thread(tw, "窗口2").start();
20 new Thread(tw, "窗口3").start();
21 new Thread(tw, "窗口4").start();
22 }
23 }
运行结果如图2所示。
图2 运行结果
实现Runnable接口后的效果
文件2中,通过实现Runnable接口的方式只创建了一个TicketWindow2对象,然后创建了四个线程。
在每个线程上都调用同一个TicketWindow2对象中的run()方法,这样就可以确保四个线程访问的是同一个tickets变量,共享100张车票。
Runnable接口或Callable接口的优势
通过上面的售票案例,并结合实际情况进行分析,通过实现Runnable接口(或者Callable接口)相对于继承Thread类实现多线程来说,有如下显著的好处:
-
适合多个线程去处理同一个共享资源的情况,把线程同程序代码、数据有效的分离,很好的体现了面向对象的设计思想。
-
可以避免Ja va单继承带来的局限性,由于一个类不能同时有两个父类,所以在当前类已经有一个父类的基础上,那么就只能采用实现Runnable接口或者Callable接口的方式来实现多线程。
结论
事实上,实际开发中大部分的多线程应用都会采用Runnable接口或者Callable接口的方式实现多线程。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- Android Spinner怎么用?和别的控件有啥区别?
- 时间:2026-08-24
-
- EasyDL与主流图像识别库性能对比分析
- 时间:2026-08-18
-
- DEEPSEEK网页版与同类AI工具功能对比分析
- 时间:2026-08-18
-
- 酷云Eye与猫眼数据平台有什么区别?功能与应用对比分析
- 时间:2026-08-15
-
- 百度API怎么选?常见方案对比与选择指南
- 时间:2026-08-07
-
- 百度AI伙伴智造未来怎么选?常见方案对比分析
- 时间:2026-08-07
-
- tftpd32怎么选?常见方案对比与使用指南
- 时间:2026-08-07
-
- Ogre3D怎么选?常见方案对比分析
- 时间:2026-08-07
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15

