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.方法对比

以下为多线程中类关系图:

image.png

从关系图中可知:

  • 三种方法实现多线程,都与Runnable接口有关
  • 从实现RUnnable接口的MyRunnable和MyCallable两种方法中,也都要通过Thread类来创建多线程

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享[2]。

总结:

实现Runnable接口比继承Thread类所具有的优势:

1):适合多个相同的程序代码的线程去处理同一个资源

2):可以避免java中的单继承的限制

3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立

4):线程池只能放入实现Runablecallable类线程,不能直接放入继承Thread的类

参考:

posted on   进击的davis  阅读(1111)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
历史上的今天:
2021-11-16 0654-最大二叉树
2021-11-16 0106-105-从中序与后序遍历序列中构造二叉树
2021-11-16 0226-翻转二叉树

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示