Java 中实现多线程的几种方法
今天到了复习的第三天,前两天完成了基础篇和JVM篇,由于JVM篇大多数是看代码和理解原理、知识点,就没过多地做博客记录。今天刚开启了多线程和并发篇,值得动手写代码来理解知识点的地方会比较多,我也会在这一篇多做博客。
首先,Java 中实现多线程有三种方法:
- 继承 Thread 类;
- 实现 Runnable 接口;
- 实现 Callable 接口,通过 FutureTask 包装器来创建 Thread 线程。
1. 继承 Thread 类
这是最传统的方法,但也是最容易理解的一种方法。通过继承 Thread 类,我们可以重写 run() 方法来定义线程要执行的任务。
public class MyThread extends Thread {
@Override
public void run() {
// 定义线程要执行的任务
}
}
2. 实现 Runnable 接口
与继承 Thread 类相比,实现 Runnable 接口是一种更加灵活的方式。因为 Runnable 接口只是一个函数接口,只包含了一个 run() 方法。因此,我们可以将 Runnable 接口作为一个参数传递给其他类,从而使该类可以执行多线程任务。
public class MyRunnable implements Runnable {
@Override
public void run() {
// 定义线程要执行的任务
}
}
public class Main {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
}
}
3. 实现 Callable 接口,通过 FutureTask 包装器来创建 Thread 线程
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
// 定义线程要执行的任务
return "Hello, world!";
}
}
public class Main {
public static void main(String[] args) throws Exception {
MyCallable callable = new MyCallable();
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> future = executorService.submit(callable);
String result = future.get();
System.out.println(result);
}
}
4. 三种方法的区别
这三种方法各有优缺点,具体选择哪种方法需要根据实际情况来决定。
- 继承 Thread 类是最简单的方法,但它缺乏灵活性。
- 实现 Runnable 接口是一种更加灵活的方式,但它不能返回结果。
- 使用Callable 和 Future 可以提供更加强大的多线程编程功能,但它相对比较复杂。
5. 如何停止一个正在运行的线程?
- 使用退出标志,使线程正常退出,也就是当 run 方法完成后线程终止。
- 使用 stop 方法强行终止,但是不推荐这个方法,因为 stop 和 suspend 及 resume 一样都是过期作废的方法。
- 使用 interrupt 方法中断线程。
class MyThread extends Thread {
volatile boolean stop = false;
public void run() {
while (!stop) {
System.out.println(getName() + " is running");
try {
sleep(1000);
} catch (InterruptedException e) {
System.out.println("week up from blcok...");
stop = true; // 在异常处理代码中修改共享变量的状态
}
}
System.out.println(getName() + " is exiting...");
}
}
class InterruptThreadDemo3 {
public static void main(String[] args) throws InterruptedException {
MyThread m1 = new MyThread();
System.out.println("Starting thread...");
m1.start();
Thread.sleep(3000);
System.out.println("Interrupt thread...: " + m1.getName());
m1.stop = true; // 设置共享变量为true
m1.interrupt(); // 阻塞时退出阻塞状态
Thread.sleep(3000); // 主线程休眠3秒以便观察线程m1的中断情况
System.out.println("Stopping application...");
}
}