以下是您提供的 14 个 Java 并发程序示例的简要执行说明和核心要点。
1. Semaphore信号量示例 (Listing 1)
- 功能:演示使用
Semaphore控制对共享资源(Shared.count)的访问,确保同一时间只有一个线程(IncThread或DecThread)能修改它。 - 执行:运行
SemDemo类的main方法。两个线程将交替获取许可、修改count并释放许可,输出结果将显示count从 0 递增到 5,再递减回 0 的序列,不会出现交错 。
2. 生产者-消费者模型 (Listing 2)
- 功能:使用两个
Semaphore(semProd和semCon) 实现经典的生产者-消费者同步,确保生产者在消费者取走数据前不会覆盖数据,消费者在没有新数据时等待 。 - 执行:运行
ProdCon类的main方法。输出将交替显示Put和Got消息,顺序为Put: 0,Got: 0,Put: 1,Got: 1... 直至 19。
3. CountDownLatch 示例 (Listing 3)
- 功能:演示
CountDownLatch用于让一个或多个线程等待其他线程完成操作。主线程调用await()等待,工作线程 (MyThread) 每完成一次任务调用countDown(),当计数器减至 0 时主线程继续执行 。 - 执行:运行
CDLDemo类的main方法。输出顺序为Starting,然后打印 0 到 4,最后打印Done。
4. CyclicBarrier 示例 (Listing 4)
- 功能:演示
CyclicBarrier让一组线程相互等待,到达屏障点后一起继续执行,并可选择执行一个屏障动作 (BarAction) 。 - 执行:运行
BarDemo类的main方法。三个线程 (A,B,C) 打印各自名称后,在await()处等待,当所有三个线程都到达后,执行BarAction打印Barrier Reached!,然后所有线程继续。
5. Exchanger 示例 (Listing 5)
- 功能:演示
Exchanger用于两个线程间交换数据。MakeString线程构建字符串,UseString线程消费字符串,两者通过exchange()方法同步交换数据 。 - 执行:运行
ExgrDemo类的main方法。MakeString生成字符串(如ABCDE),与UseString交换,UseString打印Got: ABCDE,此过程重复三次。
6. Phaser 基础示例 (Listing 6)
- 功能:演示
Phaser作为更灵活的同步屏障,支持动态注册/注销参与线程及分阶段 (Phase) 同步。主线程和工作线程 (A,B,C) 协同推进多个阶段 。 - 执行:运行
PhaserDemo类的main方法。输出将显示每个线程依次开始三个阶段,主线程在每个阶段完成后打印Phase X Complete,最后打印The Phaser is terminated。
7. 自定义 Phaser 示例 (Listing 7)
- 功能:通过继承
Phaser并重写onAdvance()方法,控制固定阶段数(本例为 4 个阶段)的执行。当所有阶段完成或注册方为 0 时,Phaser 终止 。 - 执行:运行
PhaserDemo2类的main方法。每个工作线程会循环执行阶段,直到 Phaser 终止,输出显示每个阶段的开始和完成信息。
8. Executor 框架示例 (Listing 8)
- 功能:演示使用
ExecutorService(newFixedThreadPool(2)) 管理线程池执行任务。结合CountDownLatch等待所有任务完成 。 - 执行:运行
SimpExec类的main方法。四个任务 (A,B,C,D) 被提交到只有两个线程的池中执行,每个任务打印 0 到 4。主线程等待所有任务完成后打印Done。
9. Callable 与 Future 示例 (Listing 9)
- 功能:演示使用
Callable接口(替代Runnable)提交可返回结果的任务,并通过Future对象获取结果。展示了线程池执行计算任务并汇总结果 。 - 执行:运行
CallableDemo类的main方法。三个Callable任务(计算和、斜边、阶乘)被提交执行,主线程通过Future.get()获取并打印结果(55, 5.0, 120)。
10. ReentrantLock 示例 (Listing 10)
- 功能:演示使用
ReentrantLock实现显式锁来同步对共享资源 (Shared.count) 的访问,提供了比synchronized更灵活的锁操作(如可中断、超时、公平性等)。 - 执行:运行
LockDemo类的main方法。两个线程 (A,B) 将竞争锁,获得锁的线程增加Shared.count并睡眠 1 秒,然后释放锁。输出显示锁的获取和释放过程。
11. Atomic原子变量示例 (Listing 11)
- 功能:演示使用
AtomicInteger实现无锁的线程安全计数器。getAndSet()操作是原子的,无需外部同步 。 - 执行:运行
AtomicDemo类的main方法。三个线程 (A,B,C) 并发调用Shared.ai.getAndSet(i),由于是原子操作,不会出现数据竞争,但输出顺序不确定。
12. Fork/Join 框架 (RecursiveAction) 示例 (Listing 12)
- 功能:演示使用
ForkJoinPool和RecursiveAction并行处理数组(计算平方根)。任务在数据量超过阈值 (seqThreshold) 时递归分解,利用工作窃取算法提高性能 。 - 执行:运行
ForkJoinDemo类的main方法。程序将 0 到 99999 的数组元素并行转换为平方根,并打印前 10 个元素的原始值和转换后的值。
13. Fork/Join 参数化实验示例 (Listing 13)
- 功能:扩展 Listing 12,允许通过命令行参数设置并行级别 (
parallelism) 和顺序处理阈值 (threshold),用于实验和性能调优 。 - 执行:需带两个命令行参数运行,例如
java FJExperiment 2 1000。程序将根据参数并行处理数组(偶数索引平方根,奇数索引立方根),并输出执行时间。
14. Fork/Join框架 (RecursiveTask) 示例 (Listing 14)
- 功能:演示使用
RecursiveTask<Double>执行有返回值的并行计算(数组求和)。任务递归分解,子任务结果通过fork()/join()合并 。 - 执行:运行
RecurTaskDemo类的main方法。程序并行计算一个包含正负交替值的数组的总和,并打印结果Summation 0.0(因为正负抵消)。
参考来源
- Java 多线程同步机制探秘
- Java多线程与同步机制
- 深入理解Java多线程同步机制
- Java 多线程同步机制
- Java多线程的同步机制