创建线程的三种方式
练习代码
package com.kuang.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
//回顾总结线程的创建
public class ThreadNew {
public static void main(String[] args) {
new MyThread1().start();//方式1,继承Thread类创建线程 可以 直接启动线程
new Thread(new MyThread2()).start(); //方式2,实现runnable接口创建线程,需要一个代理Thread
//方式3实现线程
FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyThread3());
new Thread(futureTask).start();
try {
Integer integer = futureTask.get();
System.out.println(integer);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
}
//方式1.继承Thread类,重写run()方法
class MyThread1 extends Thread{
@Override
public void run() {
System.out.println("第一种方式创建线程:MyThread1");
}
}
//方式2.实现Runnable接口,重写run()方法
class MyThread2 implements Runnable{
@Override
public void run() {
System.out.println("第二种方式创建线程:MyThread1");
}
}
//方式3:实现Callable接口,重写call()方法,有返回值return
class MyThread3 implements Callable{
@Override
public Integer call() throws Exception {
System.out.println("第三种方式创建线程:MyThread3");
return 100;//返回100
}
}
这段代码演示了 Java 中创建线程的三种不同方式,并对每种方式进行了简单的实现和调用。以下是代码的详细解释:
代码结构分析
-
ThreadNew
类:-
这是程序的入口类,包含
main
方法。 -
在
main
方法中,分别通过三种方式创建并启动线程。
-
-
MyThread1
类:-
这是第一种创建线程的方式:继承
Thread
类。 -
重写了
Thread
类的run
方法,定义了线程执行的任务。
-
-
MyThread2
类:-
这是第二种创建线程的方式:实现
Runnable
接口。 -
实现了
Runnable
接口的run
方法,定义了线程执行的任务。
-
-
MyThread3
类:-
这是第三种创建线程的方式:实现
Callable
接口。 -
实现了
Callable
接口的call
方法,定义了线程执行的任务,并且可以返回一个结果。
-
代码执行流程
-
方式 1:继承
Thread
类:-
创建
MyThread1
对象并调用start
方法启动线程。 -
MyThread1
的run
方法会被执行,输出"第一种方式创建线程:MyThread1"
。new MyThread1().start();
-
方式 2:实现 Runnable
接口
-
创建
MyThread2
对象,并将其作为参数传递给Thread
的构造函数。 -
调用
Thread
对象的start
方法启动线程。 -
MyThread2
的run
方法会被执行,输出"第二种方式创建线程:MyThread1"
。new Thread(new MyThread2()).start();
方式 3:实现 Callable
接口:
关键点
总结
这段代码展示了 Java 中创建线程的三种主要方式:
每种方式都有其适用的场景和优缺点,可以根据具体需求选择合适的方式。
-
创建
MyThread3
对象,并将其作为参数传递给FutureTask
的构造函数。 -
将
FutureTask
对象作为参数传递给Thread
的构造函数,并启动线程。 -
MyThread3
的call
方法会被执行,输出"第三种方式创建线程:MyThread3"
,并返回结果100
。 -
通过
FutureTask.get()
方法获取线程执行的结果,并输出该结果。FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyThread3()); new Thread(futureTask).start(); try { Integer integer = futureTask.get(); System.out.println(integer); // 输出 100 } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); }
三种创建线程的方式对比
-
方式 1:继承
Thread
类:-
优点:简单直接,适合简单的线程任务。
-
缺点:Java 是单继承的,继承
Thread
类后无法再继承其他类。
-
-
方式 2:实现
Runnable
接口:-
优点:更灵活,因为 Java 支持多实现,可以同时实现多个接口。
-
缺点:无法直接返回线程执行的结果。
-
-
方式 3:实现
Callable
接口:-
优点:可以返回线程执行的结果,并且可以抛出异常。
-
缺点:使用稍微复杂,需要通过
FutureTask
和ExecutorService
来管理线程。
-
-
Thread
类:-
直接继承
Thread
类并重写run
方法,是最基础的创建线程的方式。
-
-
Runnable
接口:-
实现
Runnable
接口并重写run
方法,然后将Runnable
对象传递给Thread
构造函数。 -
这种方式更符合面向对象的设计原则,因为它将任务和线程分离。
-
-
Callable
接口:-
实现
Callable
接口并重写call
方法,可以返回结果并抛出异常。 -
需要通过
FutureTask
或ExecutorService
来管理线程。
-
-
FutureTask
:-
用于包装
Callable
或Runnable
对象,可以获取线程执行的结果。 -
通过
get
方法获取结果时,会阻塞当前线程直到任务完成。
-
-
继承
Thread
类:适合简单的线程任务。 -
实现
Runnable
接口:更灵活,推荐使用。 -
实现
Callable
接口:可以返回结果,适合需要获取线程执行结果的场景。