Java多线程实现的方式有四种
- 继承Thread类,重写run方法
- 实现Runnable接口,重写run方法,实现Runnable接口的实现类的实例对象作为Thread构造函数的target
- 通过Callable和FutureTask创建线程
- 通过线程池创建线程
前面两种可以归结为一类:无返回值,原因很简单,通过重写run方法,run方式的返回值是void,所以没有办法返回结果
后面两种可以归结成一类:有返回值,通过Callable接口,就要实现call方法,这个方法的返回值是Object,所以返回的结果可以放在Object对象中
1、继承Thread类,重写run方法
继承Thread类:创建一个新类,继承自Thread类,然后重写run()方法。在run()方法中编写线程要执行的任务。最后创建该类的实例并调用start()方法启动线程。
class MyThread extends Thread {
@Override
public void run() {
// 线程要执行的任务
}
}
public class Main {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start(); // 启动线程
}
}
2、实现Runnable接口,重写run方法
实现Runnable接口:创建一个实现Runnable接口的类,然后在run()方法中编写线程要执行的任务。将该类的实例作为参数传递给Thread类的构造函数,然后调用start()方法启动线程。
class MyRunnable implements Runnable {
@Override
public void run() {
// 线程要执行的任务
}
}
public class Main {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start(); // 启动线程
}
}
3、通过Callable和FutureTask创建线程
要通过Callable和FutureTask创建线程,首先需要创建一个实现Callable接口的类,然后使用FutureTask将Callable对象包装起来。最后,创建一个Thread对象并将FutureTask对象作为参数传递给它。以下是一个简单的示例:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class CallableAndFutureTaskExample {
public static void main(String[] args) {
// 创建一个实现Callable接口的类
Callable<Integer> callable = new MyCallable();
// 使用FutureTask将Callable对象包装起来
FutureTask<Integer> futureTask = new FutureTask<>(callable);
// 创建一个Thread对象并将FutureTask对象作为参数传递给它
Thread thread = new Thread(futureTask);
// 启动线程
thread.start();
try {
// 获取线程执行结果
int result = futureTask.get();
System.out.println("线程执行结果: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
// 模拟耗时操作
Thread.sleep(1000);
return 42;
}
}
在这个示例中,我们创建了一个名为MyCallable的类,它实现了Callable接口。在call()方法中,我们模拟了一个耗时操作(例如计算斐波那契数列)。然后,我们创建了一个FutureTask对象,将MyCallable对象作为参数传递给它。接下来,我们创建了一个Thread对象,并将FutureTask对象作为参数传递给它。最后,我们启动了线程并等待其执行完成,然后获取并打印线程执行结果。
4、通过线程池创建线程
要通过线程池创建线程,可以使用Java中的ExecutorService
接口和Executors
工具类。以下是一个简单的示例:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
// 创建一个固定大小的线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 提交任务到线程池
for (int i = 0; i < 10; i++) {
Runnable task = new MyTask(i);
executorService.submit(task);
}
// 关闭线程池
executorService.shutdown();
}
}
class MyTask implements Runnable {
private int taskId;
public MyTask(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("Task " + taskId + " is running by " + Thread.currentThread().getName());
}
}
在这个示例中,我们创建了一个固定大小为5的线程池,然后提交了10个任务到线程池。每个任务都是一个实现了Runnable
接口的MyTask
类的实例。线程池会自动分配线程来执行这些任务。最后,我们调用shutdown()
方法关闭线程池。