欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > Java线程与线程池解析

Java线程与线程池解析

2025/9/16 10:17:03 来源:https://blog.csdn.net/qq_45351273/article/details/147717837  浏览:    关键词:Java线程与线程池解析

一、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. 工作流程

  1. 提交任务后,如果运行线程数 < corePoolSize,创建新线程执行
  2. 如果运行线程数 ≥ corePoolSize,任务放入工作队列
  3. 如果队列已满且运行线程数 < maximumPoolSize,创建新线程执行
  4. 如果队列已满且运行线程数 ≥ 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); // 输出 "Hello World"

七、虚拟线程 (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. 上下文切换开销

  • 优化
    • 减少同步代码块范围
    • 使用并发集合
    • 考虑无锁编程

九、性能调优建议

  1. IO密集型:增大线程池大小
  2. CPU密集型:控制线程数≈CPU核心数
  3. 减少锁竞争
    • 缩小同步范围
    • 使用读写锁
    • 考虑CAS操作
  4. 监控指标
    • 线程池活跃度
    • 队列大小
    • 任务执行时间

十、总结

Java线程和线程池是并发编程的核心,合理使用可以显著提升系统性能。关键要点:

  1. 线程创建:优先使用线程池而非直接创建线程
  2. 线程池配置:根据任务类型选择合适参数
  3. 线程安全:正确使用同步机制和并发集合
  4. 现代特性:利用CompletableFuture简化异步编程
  5. 新趋势:关注虚拟线程等新特性

通过深入理解这些概念和技术,开发者可以构建出高效、可靠的并发应用程序。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词