Java中线程间的通信机制主要用于协调多个线程之间的协作,使得它们能够在特定的时机交换信息、同步执行或触发特定行为。
以下是Java中常用的线程间通信机制:
- 共享变量与同步机制:
- volatile关键字:用来修饰共享变量,确保线程对变量的修改对其他线程立即可见,消除指令重排序带来的影响,适用于简单的状态标记等场景。
- synchronized关键字:用于实现临界区同步,通过锁定特定对象,确保同一时刻只有一个线程访问共享资源。在synchronized代码块或方法中,可以安全地修改共享变量,同时配合wait()、notify()、notifyAll()方法实现线程间的通信。
- wait():当前线程释放锁并进入等待状态,直到被其他线程调用notify()或notifyAll()唤醒。
- notify():唤醒一个因调用wait()而处于等待状态的线程。
- notifyAll():唤醒所有因调用wait()而处于等待状态的线程。
/**
* 共享变量与同步机制(synchronized + wait/notify)
*/
public class SharedVarExample {
private int value;
private final Object lock = new Object();
public void increment() {
synchronized (lock) {
value++;
System.out.printf("增加value值为:%d\n", value);
lock.notify();//唤醒等待的线程
}
}
public void decrement() {
synchronized (lock) {
while (value == 0) {
//条件不满足时等待
try {
System.out.println("等待value值被修改...");
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
value--;
System.out.printf("减少value值为:%d\n", value);
}
}
public static void main(String[] args) throws InterruptedException {
SharedVarExample example = new SharedVarExample();
//创建修改共享资源的线程
Thread updateThread = new Thread(new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1); //模拟延迟,确保等待线程先启动
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
example.increment();
}
});
//创建等待共享资源变化的线程
Thread waitThread = new Thread(new Runnable() {
@Override
public void run() {
example.decrement();
}
});
//启动线程
waitThread.start();
updateThread.start();
//等待两个线程结束
waitThread.join();
updateThread.join();
System.out.println("两个线程都执行完了。");
}
//执行结果
/*
等待value值被修改...
增加value值为:1
减少value值为:0
两个线程都执行完了。
*/
}
- Lock与Condition接口:
- ReentrantLock:可重入锁,比synchronized提供了更灵活的锁定机制,如公平锁、非公平锁的选择,以及尝试加锁、定时加锁等操作。
- Condition:与ReentrantLock配套使用,替代了synchronized的wait/notify机制。每个Condition对象都关联一个Lock,线程可以调用condition.await()进入等待状态,并在其他线程调用condition.signal()或condition.signalAll()时被唤醒。Condition允许创建多个等待-通知条件,适用于更为复杂的同步场景。
/**
* Lock与Condition接口
*/
public class LockConditionExample {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private boolea