Java面试题之多线程 线程之间是如何通信的?
在Java中,线程之间的通信主要通过以下几种方式实现:
共享变量:
synchronized
关键字来同步对共享变量的访问。wait()
和 notify()
方法:
wait()
和 notify()
方法实现线程间的通信。wait()
方法使当前线程等待,直到其他线程调用同一对象的 notify()
或 notifyAll()
方法。notify()
方法会唤醒在该对象监视器上等待的单个线程,而 notifyAll()
会唤醒所有等待的线程。示例代码:
class SharedResource {
private int data;
private boolean available = false;
public synchronized int get() throws InterruptedException {
while (!available) {
wait(); // 等待数据可用
}
available = false;
notify(); // 通知生产者可以生产
return data;
}
public synchronized void put(int value) throws InterruptedException {
while (available) {
wait(); // 等待数据被消费
}
data = value;
available = true;
notify(); // 通知消费者可以消费
}
}
BlockingQueue
:
java.util.concurrent
包中的BlockingQueue
接口及其实现(如ArrayBlockingQueue
、LinkedBlockingQueue
等),可以用于线程间的通信。BlockingQueue
提供了线程安全的队列操作,生产者可以将数据放入队列,消费者可以从队列中取出数据,且在队列为空或满时会自动阻塞。示例代码:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
class Producer implements Runnable {
private BlockingQueue<Integer> queue;
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
queue.put(i);
System.out.println("Produced: " + i);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
class Consumer implements Runnable {
private BlockingQueue<Integer> queue;
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
int value = queue.take();
System.out.println("Consumed: " + value);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
CountDownLatch
和 CyclicBarrier
:
CountDownLatch
可以使一个或多个线程等待直到在其他线程中执行的一组操作完成,而CyclicBarrier
允许一组线程互相等待,直到到达某个公共屏障点。Semaphore
:
Semaphore
是一个计数信号量,可以用于控制对共享资源的访问。它可以用于实现线程间的通信和协调。通过以上方式,Java中的线程可以有效地进行通信和协作。选择合适的通信方式取决于具体的应用场景和需求。