在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.定义类,实现 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的类
参考:
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |