三种创建线程的方式:
- 继承 Thread 类
- 实现 Runnable 接口
- 实现 Callable 接口
1 继承 Thread 类
创建步骤
- 自定义线程类
- 重写
run()方法 调用
start()方法执行线程 ```java public class MyThread extends Thread { @Override public void run() {for (int i = 0; i < 100; i++) {System.out.println("Child thread...");try {sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
public static void main(String[] args) {
MyThread thread = new MyThread();thread.start();for (int i = 0; i < 100; i++) {System.out.println("Main thread...");try {sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}
} }
> 注意:> - 调用`start()`方法后,子线程不一定立刻执行,要通过 CPU 调度> - `sleep()`方法需要使用`try-catch`语句示例```javaimport org.apache.commons.io.FileUtils;import java.io.File;import java.io.IOException;import java.net.URL;public class WebDownloader extends Thread {private String url;private String fileName;public WebDownloader(String url, String fileName) {this.url = url;this.fileName = fileName;}@Overridepublic void run() {download(this.url, this.fileName);System.out.println("File downloaded: " + this.fileName + " from " + this.url);}public static void download(String url, String fileName) {try {FileUtils.copyURLToFile(new URL(url), new File(fileName));} catch (IOException e) {e.printStackTrace();throw new RuntimeException(e);}}public static void main(String[] args) {WebDownloader w1 = new WebDownloader("https://www.baidu.com/", "baidu1.html");WebDownloader w2 = new WebDownloader("https://www.baidu.com/", "baidu2.html");WebDownloader w3 = new WebDownloader("https://www.baidu.com/", "baidu3.html");w1.start();w2.start();w3.start();}}
需要导入 commons-io 包,可以使用 maven 导入:
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version></dependency>
2 实现 Runnable 接口
创建步骤
- 定义类并实现 Runnable 接口
- 实现
run()方法 创建线程对象,调用
start()方法public class MyThread implements Runnable {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("Child thread...");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}public static void main(String[] args) {// 创建实现了 Runnable 接口的类MyThread myThread = new MyThread();// 使用 Runnable 对象构造 Thread 类Thread thread = new Thread(myThread);thread.start();for (int i = 0; i < 100; i++) {System.out.println("Main thread...");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}
官方的 Thread 类也是实现了 Runnable 接口,而 Runnable 接口只规定了一个
run()方法。
3 实现 Callable 接口
创建步骤
- 实现 Callable 接口,需要返回值类型
- 重写 call 方法,需要抛出异常
- 创建目标对象
- 创建执行服务:
ExecutorService ser = Executors.newFixedThreadPool(1); - 提交执行:
Future<Boolean> result1 = ser.submit(t1); - 获取执行结果:
boolean res1 = result1.get(); - 关闭服务:
ser.shutdownNow();```java import java.util.concurrent.*;
public class MyCallable implements Callable
public MyCallable(String name) {this.name = name;}@Overridepublic Boolean call() throws Exception {for (int i = 0; i < 10; i++) {System.out.println("Thread " + this.name + " running...");Thread.sleep(1000);}return false;}public static void main(String[] args) throws ExecutionException, InterruptedException {Callable<Boolean> c1 = new MyCallable("t1");Callable<Boolean> c2 = new MyCallable("t2");Callable<Boolean> c3 = new MyCallable("t3");// 创建执行服务ExecutorService ser = Executors.newFixedThreadPool(3);// 提交执行Future<Boolean> result1 = ser.submit(c1);Future<Boolean> result2 = ser.submit(c2);Future<Boolean> result3 = ser.submit(c3);boolean res1 = result1.get();boolean res2 = result2.get();boolean res3 = result3.get();ser.shutdownNow();}
}
> 通过 Callable 创建线程的**好处**:> - 可以拿到线程执行的返回值> - 可以抛出异常<a name="eACvi"></a>## %% 创建方式的比较**实践中一般通过实现 Runnable 接口来创建线程,而不使用继承 Thread 类的方式。**<br />原因如下:1. 由于 Java 中只能单继承的局限性,一个类如果继承了 Thread 类,就不能在继承其他类1. 使用 Runnable,可以让多个线程执行同一个 Runnable 对象的`run()`方法,可以共享同一类的变量,代码如下:```javaCallable myThread = new MyThread();// 使用同一个 Runnable 对象执行不同的线程Thread t1 = new Thread(myThread);Thread t2 = new Thread(myThread);Thread t3 = new Thread(myThread);t1.start();t2.start();t3.start();
如果需要返回值,或者线程抛出异常的情况,则应该使用 Callable 创建线程。
