Java 创建多线程的三种方法
在Java中创建多线程,往往都要通过Thread类来实现,今天学习下Java中创建多线程的三种方法[1]。
1.继承Thread类
通过继承 Thread类 实现多线程。
主要方法:
- 1.void run(), 线程开启后,方法将被调用执行
- 2.void start(), 使此线程开始执行, Java虚拟机会调用run()方法
实现步骤:
- 1.定义类,继承 Thread类
- 2.重写 run() 方法
- 3.创建多线程类对象
- 4.通过实例方法 start() 启动线程
demo
public class MyThreadExtendsThread extends Thread { private int num; public MyThreadExtendsThread() {}; public MyThreadExtendsThread(int num) { this.num = num; } @Override public void run() { for (int i = 0; i < num; i++) { System.out.println(Thread.currentThread().getName() + " 子线程:" + i); } } public static void main(String[] args) throws InterruptedException { Thread t1 = new MyThreadExtendsThread(); Thread t2 = new MyThreadExtendsThread(100000); t2.setDaemon(true); // true, 主线程结束,子线程也随之退出, false, 主线程结束后,子线程继续执行 t1.start(); t2.start(); for (int i = 0; i < 10; i++) { System.out.println("主线程:" + i); } // 等待子线程完成任务 Thread.sleep(10L); /* 子线程:0 子线程:1 主线程:0 子线程:2 主线程:1 主线程:2 主线程:3 主线程:4 主线程:5 主线程:6 主线程:7 子线程:3 子线程:4 子线程:5 子线程:6 子线程:7 子线程:8 子线程:9 主线程:8 主线程:9 */ } }
2.实现Runnable接口
通过实现 Runnable接口 实现多线程。
主要方法:
- 1.void run(),重写run方法
实现步骤:
- 1.定义类,实现 Runnable 接口
- 2.类中重写 run()方法
- 3.创建多线程类对象
- 4.创建 Thread 类对象,通过传入多线程类对象作为构造方法参数
- 5.通过 Thread 类对象的 start 方法启动线程
demo
public class MyThreadImplementsRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println("子线程:" + i); } } public static void main(String[] args) throws InterruptedException { Runnable t1 = new MyThreadImplementsRunnable(); new Thread(t1).start(); for (int i = 0; i < 5; i++) { System.out.println("主线程:" + i); } Thread.sleep(1000L); /* 子线程:0 主线程:0 主线程:1 主线程:2 主线程:3 主线程:4 子线程:1 子线程:2 子线程:3 子线程:4 */ } }
3.实现Callable接口
通过实现 Callable接口 实现多线程。
主要方法:
- 1.V call(), 计算结果,如无,则抛出异常
- 2.V get(), 如必要,等待计算完成,然后获取结果
实现步骤:
- 1.定义类实现 Callable 接口
- 2.在刚定义的类中重写 call()方法
- 3.创建 MyThreadImplementsCallable 对象
- 4.创建 Future 接口的实现类 FutureTask 对象,传入 MyThreadImplementsCallable 作为构造方法的参数
- 5.创建 Thread 类对象,传入FutureTask作为构造方法参数
- 6.启动线程
- 7.如有需要,通过调用 get() 方法, 获取线程任务结束后的结果
demo
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class MyThreadImplementsCallable implements Callable { private int num; public MyThreadImplementsCallable(int num) { this.num = num; } @Override public String call() throws Exception { int sum = 0; for (int i = 0; i < num; i++) { sum += i; } return "线程求出 -> " + num + "之内的和为:" + sum; } public static void main(String[] args) throws InterruptedException, ExecutionException { Callable callable = new MyThreadImplementsCallable(1000); // 创建未来任务实现Callable接口 FutureTask<String> futureTask = new FutureTask<>(callable); new Thread(futureTask).start(); // 获取线程任务结束后的结果 String res = futureTask.get(); System.out.println("res: " + res); // res: 线程求出 -> 1000之内的和为:499500 } }
4.方法对比
以下为多线程中类关系图:
从关系图中可知:
- 三种方法实现多线程,都与Runnable接口有关
- 从实现RUnnable接口的MyRunnable和MyCallable两种方法中,也都要通过Thread类来创建多线程
如果一个类继承Thread
,则不适合资源共享。但是如果实现了Runable
接口的话,则很容易的实现资源共享[2]。
总结:
实现Runnable
接口比继承Thread
类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java
中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
4):线程池只能放入实现Runable
或callable
类线程,不能直接放入继承Thread
的类
参考:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
2021-11-16 0654-最大二叉树
2021-11-16 0106-105-从中序与后序遍历序列中构造二叉树
2021-11-16 0226-翻转二叉树