Java多线程通信方式详解

Java Q&A Hub 使用 GPT-4o-mini 回答

问题:

Java面试题之多线程 线程之间是如何通信的?

回答:

在Java中,线程之间的通信主要通过以下几种方式实现:

  1. 共享变量

    • 线程可以通过共享变量来进行通信。多个线程可以访问同一个对象的属性,通过对这些属性的读写来传递信息。为了确保线程安全,通常需要使用 synchronized 关键字来同步对共享变量的访问。
  2. wait()notify() 方法

    • Java的对象都有一个监视器锁(monitor),可以通过 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(); // 通知消费者可以消费
        }
    }
    
  3. BlockingQueue

    • Java提供了java.util.concurrent包中的BlockingQueue接口及其实现(如ArrayBlockingQueueLinkedBlockingQueue等),可以用于线程间的通信。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();
            }
        }
    }
    
  4. CountDownLatchCyclicBarrier

    • 这些是用于线程间协调的工具,CountDownLatch可以使一个或多个线程等待直到在其他线程中执行的一组操作完成,而CyclicBarrier允许一组线程互相等待,直到到达某个公共屏障点。
  5. Semaphore

    • Semaphore是一个计数信号量,可以用于控制对共享资源的访问。它可以用于实现线程间的通信和协调。

通过以上方式,Java中的线程可以有效地进行通信和协作。选择合适的通信方式取决于具体的应用场景和需求。