线程通信的4种方式
线程通信常用的方式有:
- wait/notify 等待
- Volatile 内存共享
- CountDownLatch 并发工具
- CyclicBarrier 并发工具
wait/notify
两个线程交替打印奇偶数,通过wait/notify
实现
copypublic class WaitNotify {
// 状态锁
private static Object lock = new Object();
private static Integer i = 0;
public void odd() {
while (i < 10) {
synchronized (lock) {
if (i % 2 == 1) {
System.out.println(Thread.currentThread().getName() + " - " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
lock.notify();
} else {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public void even() {
while (i < 10) {
synchronized (lock) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + " - " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
lock.notify();
} else {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) {
WaitNotify waitNotify = new WaitNotify();
Thread t1 = new Thread(() -> waitNotify.odd(), "线程1");
Thread t2 = new Thread(() -> waitNotify.even(), "线程2");
t1.start();
t2.start();
}
}
↓展开↓
结果:
copy线程2 - 0
线程1 - 1
线程2 - 2
线程1 - 3
线程2 - 4
线程1 - 5
线程2 - 6
线程1 - 7
线程2 - 8
线程1 - 9
线程2 - 10
Volatile
volatile
修饰内存可见性
copypublic class Volatile implements Runnable {
private static volatile Boolean flag = true;
@Override
public void run() {
while (flag) {
System.out.println(Thread.currentThread().getName() + " - 执行");
}
System.out.println("线程结束");
}
public static void main(String[] args) {
Thread t = new Thread(new Volatile());
t.start();
try {
Thread.sleep(5);
flag = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
↓展开↓
结果:
copyThread-0 - 执行
Thread-0 - 执行
Thread-0 - 执行
Thread-0 - 执行
Thread-0 - 执行
线程结束
CountDownLatch
CountDownLatch
可以代替wait/notify
的使用,并去掉synchronized
,下面重写第一个例子:
copyimport java.util.concurrent.CountDownLatch;
public class CountDown {
private static Integer i = 0;
final static CountDownLatch countDown = new CountDownLatch(1);
public void odd() {
while (i < 10) {
if (i % 2 == 1) {
System.out.println(Thread.currentThread().getName() + " - " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
countDown.countDown();
} else {
try {
countDown.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void even() {
while (i < 10) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + " - " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
countDown.countDown();
} else {
try {
countDown.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
CountDown countDown = new CountDown();
Thread t1 = new Thread(() -> countDown.odd(), "线程1");
Thread t2 = new Thread(() -> countDown.even(), "线程2");
t1.start();
t2.start();
}
}
↓展开↓
CyclicBarrier
等待N个线程都达到某个状态后继续运行
copyimport java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierTest {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + ": 准备...");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("全部启动完毕!");
}, "线程1").start();
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + ": 准备...");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("全部启动完毕!");
}, "线程2").start();
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + ": 准备...");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("全部启动完毕!");
}, "线程3").start();
}
}
↓展开↓
结果:
copy线程3: 准备...
线程2: 准备...
线程1: 准备...
全部启动完毕!
全部启动完毕!
全部启动完毕!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通