一、Java线程基础
1. 线程创建方式
方式一:继承Thread类
class MyThread extends Thread {@Overridepublic void run() {System.out.println("线程执行: " + Thread.currentThread().getName());}
}
MyThread thread = new MyThread();
thread.start();
方式二:实现Runnable接口
class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("线程执行: " + Thread.currentThread().getName());}
}
Thread thread = new Thread(new MyRunnable());
thread.start();
方式三:实现Callable接口(Java 5+)
class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {return "线程执行结果: " + Thread.currentThread().getName();}
}
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new MyCallable());
System.out.println(future.get());
executor.shutdown();
方式四:Lambda表达式(Java 8+)
new Thread(() -> {System.out.println("Lambda线程: " + Thread.currentThread().getName());
}).start();
2. 线程生命周期
新建(New) → 就绪(Runnable) ←→ 运行(Running) → 阻塞(Blocked)↓ ↑└────── 等待(Waiting) ←───────┘↓└── 超时等待(Timed Waiting) → 终止(Terminated)
二、线程池详解
1. 为什么需要线程池
- 降低资源消耗:减少线程创建和销毁的开销
- 提高响应速度:任务到达时线程已存在
- 提高线程可管理性:统一分配、调优和监控
- 防止资源耗尽:通过限制线程数量
2. ThreadPoolExecutor核心参数
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler
)
3. 工作流程
- 提交任务后,如果运行线程数 < corePoolSize,创建新线程执行
- 如果运行线程数 ≥ corePoolSize,任务放入工作队列
- 如果队列已满且运行线程数 < maximumPoolSize,创建新线程执行
- 如果队列已满且运行线程数 ≥ maximumPoolSize,执行拒绝策略
4. 常见线程池类型
(1) FixedThreadPool
ExecutorService fixedPool = Executors.newFixedThreadPool(5);
- 固定大小线程池
- 核心线程数 = 最大线程数
- 使用无界队列LinkedBlockingQueue
(2) CachedThreadPool
ExecutorService cachedPool = Executors.newCachedThreadPool();
- 可缓存线程池
- 核心线程数=0,最大线程数=Integer.MAX_VALUE
- 使用SynchronousQueue
(3) SingleThreadExecutor
ExecutorService singlePool = Executors.newSingleThreadExecutor();
- 单线程池
- 保证任务顺序执行
- 使用无界队列LinkedBlockingQueue
(4) ScheduledThreadPool
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3);
5. 任务队列类型
| 队列类型 | 特性 | 适用场景 |
|---|
| LinkedBlockingQueue | 无界队列 | 任务量波动不大 |
| ArrayBlockingQueue | 有界队列 | 防止资源耗尽 |
| SynchronousQueue | 不存储元素 | 直接传递任务 |
| PriorityBlockingQueue | 优先级队列 | 任务有优先级区分 |
| DelayedWorkQueue | 延迟队列 | 定时任务 |
6. 拒绝策略
| 策略 | 行为 | 实现类 |
|---|
| AbortPolicy | 抛出RejectedExecutionException | 默认策略 |
| CallerRunsPolicy | 由调用者线程执行任务 | 适合不允许失败场景 |
| DiscardPolicy | 直接丢弃任务 | 适合无关紧要任务 |
| DiscardOldestPolicy | 丢弃队列最前面的任务 | 适合新任务更重要的场景 |
三、线程池最佳实践
1. 线程池大小配置
- CPU密集型:核心线程数 = CPU核数 + 1
- IO密集型:核心线程数 = CPU核数 × (1 + 平均等待时间/平均计算时间)
int corePoolSize = Runtime.getRuntime().availableProcessors() * 2;
2. 自定义线程工厂
ThreadFactory factory = r -> {Thread thread = new Thread(r);thread.setName("custom-thread-" + thread.getId());thread.setPriority(Thread.NORM_PRIORITY);thread.setUncaughtExceptionHandler((t, e) -> {System.err.println("线程异常: " + t.getName() + ", error: " + e.getMessage());});return thread;
};
3. 监控线程池状态
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);
ScheduledExecutorService monitor = Executors.newSingleThreadScheduledExecutor();
monitor.scheduleAtFixedRate(() -> {System.out.println("活跃线程数: " + executor.getActiveCount());System.out.println("完成任务数: " + executor.getCompletedTaskCount());System.out.println("队列大小: " + executor.getQueue().size());
}, 0, 1, TimeUnit.SECONDS);
4. 优雅关闭线程池
executor.shutdown();
try {if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {executor.shutdownNow(); }
} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();
}
四、高级线程概念
1. 线程安全与同步
synchronized关键字
public synchronized void increment() {count++;
}
public void update() {synchronized(this) {}
}
ReentrantLock
private final Lock lock = new ReentrantLock();public void performTask() {lock.lock();try {} finally {lock.unlock();}
}
volatile关键字
private volatile boolean running = true;public void stop() {running = false;
}
2. 并发工具类
CountDownLatch
CountDownLatch latch = new CountDownLatch(3);
new Thread(() -> {latch.countDown();
}).start();
latch.await();
CyclicBarrier
CyclicBarrier barrier = new CyclicBarrier(3, () -> {System.out.println("所有线程到达屏障");
});
new Thread(() -> {barrier.await();
}).start();
Semaphore
Semaphore semaphore = new Semaphore(3); semaphore.acquire();
try {
} finally {semaphore.release();
}
3. 原子类
AtomicInteger counter = new AtomicInteger(0);counter.incrementAndGet();
五、Java并发集合
1. ConcurrentHashMap
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("key", 1);
map.computeIfAbsent("anotherKey", k -> 2);
2. CopyOnWriteArrayList
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("item");
list.get(0);
3. BlockingQueue
BlockingQueue<String> queue = new LinkedBlockingQueue<>(10);
queue.put("element");
String element = queue.take();
六、CompletableFuture (Java 8+)
1. 异步编程
CompletableFuture.supplyAsync(() -> {return "结果";
}).thenApply(result -> {return result + "处理";
}).thenAccept(finalResult -> {System.out.println(finalResult);
});
2. 组合多个Future
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2).thenAccept(System.out::println);
七、虚拟线程 (Java 19+)
1. 轻量级线程
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {executor.submit(() -> {System.out.println("虚拟线程执行");});
}
2. 与传统线程对比
| 特性 | 平台线程 | 虚拟线程 |
|---|
| 资源消耗 | 高 (1MB+) | 低 (~KB) |
| 创建数量 | 有限 (数千) | 百万级 |
| 调度方式 | OS调度 | JVM调度 |
| 阻塞代价 | 高 | 低 |
八、常见问题与解决方案
1. 线程池任务堆积
2. 线程泄漏
3. 死锁问题
- 检测:jstack或VisualVM
- 预防:
- 避免嵌套锁
- 使用定时锁tryLock
- 按固定顺序获取锁
4. 上下文切换开销
九、性能调优建议
- IO密集型:增大线程池大小
- CPU密集型:控制线程数≈CPU核心数
- 减少锁竞争:
- 监控指标:
十、总结
Java线程和线程池是并发编程的核心,合理使用可以显著提升系统性能。关键要点:
- 线程创建:优先使用线程池而非直接创建线程
- 线程池配置:根据任务类型选择合适参数
- 线程安全:正确使用同步机制和并发集合
- 现代特性:利用CompletableFuture简化异步编程
- 新趋势:关注虚拟线程等新特性
通过深入理解这些概念和技术,开发者可以构建出高效、可靠的并发应用程序。