如何在Java中进行多线程编程
在Java中进行多线程编程有多种方式,最常用的包括继承Thread类、实现Runnable接口、实现Callable接口,以及使用线程池等。以下是具体介绍和代码示例:
1. 继承Thread类
通过继承Thread类并重写run()方法来定义线程执行逻辑,然后调用start()方法启动线程。
// 继承Thread类
class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("线程" + Thread.currentThread().getId() + ": " + i);
try {
Thread.sleep(100); // 休眠100毫秒,模拟任务耗时
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadExample {
public static void main(String[] args) {
// 创建并启动线程
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
thread1.start(); // 启动线程(调用run()方法)
thread2.start();
}
}
2. 实现Runnable接口
实现Runnable接口的run()方法,将任务逻辑与线程分离,更灵活(可避免单继承限制)。
// 实现Runnable接口
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("线程" + Thread.currentThread().getId() + ": " + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class RunnableExample {
public static void main(String[] args) {
// 创建任务实例
MyRunnable task = new MyRunnable();
// 通过Thread包装任务并启动
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
}
}
3. 实现Callable接口(带返回值)
Callable接口与Runnable类似,但call()方法可以返回结果并抛出异常,通常配合Future使用。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
// 实现Callable接口(泛型指定返回值类型)
class MyCallable implements Callable<Integer> {
private int taskId;
public MyCallable(int taskId) {
this.taskId = taskId;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i <= 10; i++) {
sum += i;
Thread.sleep(50);
}
System.out.println("任务" + taskId + "执行完毕,结果为:" + sum);
return sum; // 返回计算结果
}
}
public class CallableExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建Callable任务
MyCallable task1 = new MyCallable(1);
MyCallable task2 = new MyCallable(2);
// 用FutureTask包装Callable(可获取结果)
FutureTask<Integer> future1 = new FutureTask<>(task1);
FutureTask<Integer> future2 = new FutureTask<>(task2);
// 启动线程
new Thread(future1).start();
new Thread(future2).start();
// 获取任务结果(会阻塞直到任务完成)
int result1 = future1.get();
int result2 = future2.get();
System.out.println("主线程获取结果:" + result1 + "," + result2);
}
}
4. 使用线程池(推荐)
频繁创建销毁线程会消耗资源,线程池可以复用线程,提高效率。Java通过Executors或ThreadPoolExecutor创建线程池。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
// 创建固定大小的线程池(3个线程)
ExecutorService executor = Executors.newFixedThreadPool(3);
// 提交5个任务到线程池
for (int i = 0; i < 5; i++) {
final int taskId = i;
executor.submit(() -> {
// 使用Lambda表达式简化Runnable
System.out.println("任务" + taskId + "由线程" + Thread.currentThread().getId() + "执行");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
// 关闭线程池(不再接受新任务,等待现有任务完成)
executor.shutdown();
}
}
核心概念补充
- 线程状态:新建(New)→ 就绪(Runnable)→ 运行(Running)→ 阻塞(Blocked/Waiting/Timed Waiting)→ 终止(Terminated)。
- 线程同步:多线程共享资源时需避免竞争,可使用
synchronized关键字、Lock接口等实现同步。 - 线程通信:通过
wait()、notify()、notifyAll()等方法实现线程间协作。
线程池是实际开发中推荐的方式,因为它能更好地管理线程资源,避免频繁创建线程的开销。
浙公网安备 33010602011771号