掌握线程创建、同步机制、线程池使用和并发编程最佳实践
Java提供了多种创建线程的方式,每种方式都有其特定的优势和适用场景。理解这些方式的区别对于编写高效的多线程程序至关重要。
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程执行中...");
}
}
// 使用
MyThread thread = new MyThread();
thread.start();
class MyTask implements Runnable {
@Override
public void run() {
System.out.println("任务执行中...");
}
}
// 使用
Thread thread = new Thread(new MyTask());
thread.start();
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "任务执行结果";
}
}
// 使用
FutureTask<String> task = new FutureTask<>(new MyCallable());
Thread thread = new Thread(task);
thread.start();
String result = task.get(); // 获取结果
在多线程环境中,同步机制是确保数据一致性和避免竞态条件的关键。Java提供了多种同步机制来满足不同的需求。
同步机制 | 特点 | 适用场景 | 性能影响 |
---|---|---|---|
synchronized |
内置锁,可重入 | 简单的同步需求 | 中等 |
volatile |
保证可见性,禁止重排序 | 简单状态标记 | 低 |
ReentrantLock |
显式锁,功能丰富 | 复杂的锁控制 | 中等 |
ReadWriteLock |
读写分离锁 | 读多写少场景 | 低(读操作) |
Atomic类 |
原子操作,无锁 | 简单的原子更新 | 很低 |
线程池是管理和复用线程的重要工具,能够显著提高应用程序的性能和资源利用率。
// 创建自定义线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // 核心线程数
10, // 最大线程数
60L, // 空闲存活时间
TimeUnit.SECONDS, // 时间单位
new LinkedBlockingQueue<>(100), // 任务队列
Executors.defaultThreadFactory(), // 线程工厂
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
// 提交任务
executor.submit(() -> {
System.out.println("任务执行中:" + Thread.currentThread().getName());
});
// 关闭线程池
executor.shutdown();
/**
* Java多线程基础示例
* 演示三种线程创建方式的使用
*
* @author Java学习者
* @version 1.0
* @since 2024-01-05
*/
public class ThreadBasics {
public static void main(String[] args) {
System.out.println("=== Java多线程编程示例 ===");
// 方式1:继承Thread类
demonstrateThreadClass();
// 方式2:实现Runnable接口
demonstrateRunnableInterface();
// 方式3:实现Callable接口
demonstrateCallableInterface();
}
/**
* 演示继承Thread类的方式
*/
private static void demonstrateThreadClass() {
System.out.println("\n1. 继承Thread类创建线程:");
MyThread thread = new MyThread("Thread-1");
thread.start();
try {
thread.join(); // 等待线程执行完成
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
/**
* 演示实现Runnable接口的方式
*/
private static void demonstrateRunnableInterface() {
System.out.println("\n2. 实现Runnable接口创建线程:");
MyTask task = new MyTask("Task-1");
Thread thread = new Thread(task, "Thread-2");
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
/**
* 演示实现Callable接口的方式
*/
private static void demonstrateCallableInterface() {
System.out.println("\n3. 实现Callable接口创建线程:");
MyCallable callable = new MyCallable("Callable-1");
FutureTask<String> futureTask = new FutureTask<>(callable);
Thread thread = new Thread(futureTask, "Thread-3");
thread.start();
try {
String result = futureTask.get(); // 获取执行结果
System.out.println("任务执行结果:" + result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 使用线程池管理线程
ExecutorService executor = Executors.newFixedThreadPool(5);
// 合理设置线程名称
Thread.currentThread().setName("DataProcessor-" + id);
// 正确处理中断
if (Thread.currentThread().isInterrupted()) {
return; // 响应中断
}
// 使用并发工具类
CountDownLatch latch = new CountDownLatch(3);
// 避免:频繁创建线程
for (int i = 0; i < 1000; i++) {
new Thread(() -> doWork()).start();
}
// 避免:忽略异常
try {
thread.join();
} catch (InterruptedException e) {
// 空catch块
}
// 避免:不合理的锁粒度
synchronized (this) {
// 大量耗时操作
}