线程间通信是指在多个线程之间传递数据和同步它们的执行。Java提供了几种线程间通信的方法,包括:
wait()
、notify()
和notifyAll()
java.util.concurrent
包中的工具类线程可以通过访问共享变量实现通信。为了确保线程安全,我们需要对共享变量的访问进行同步。我们可以使用synchronized
关键字来实现同步。
示例:两个线程通过共享变量实现通信
class SharedCounter { private int counter = 0; public synchronized void increment() { counter++; System.out.println("Counter: " + counter); } } public class SharedVariableExample { public static void main(String[] args) { SharedCounter sharedCounter = new SharedCounter(); Thread t1 = new Thread(() -> { for (int i = 0; i < 10; i++) { sharedCounter.increment(); } }); Thread t2 = new Thread(() -> { for (int i = 0; i < 10; i++) { sharedCounter.increment(); } }); t1.start(); t2.start(); } }
在上述示例中,我们创建了一个SharedCounter
类,它有一个共享变量counter
。两个线程通过调用increment()
方法来递增计数器。我们使用synchronized
关键字确保了对计数器的同步访问。
wait()
、notify()
和notifyAll()
wait()
、notify()
和notifyAll()
是java.lang.Object
类的方法,可以用于在线程间实现通信。这些方法必须在同步代码块或同步方法中使用。
wait()
: 使当前线程等待,直到其他线程调用此对象的notify()
或notifyAll()
方法。调用wait()
时,线程会释放锁,允许其他线程进入同步代码块或同步方法。notify()
: 唤醒等待此对象锁的单个线程。如果有多个线程在等待,只有一个线程会被唤醒。notifyAll()
: 唤醒等待此对象锁的所有线程。示例:使用wait()
和notify()
实现生产者-消费者问题
import java.util.LinkedList; import java.util.Queue; class ProducerConsumer { private Queue<Integer> queue = new LinkedList<>(); private int maxSize; public ProducerConsumer(int maxSize) { this.maxSize = maxSize; } public void produce() throws InterruptedException { int value = 0; while (true) { synchronized (this) { while (queue.size() == maxSize) { wait(); } System.out.println("Produced: " + value); queue.offer(value++); notify(); Thread.sleep(1000); } } } public void consume() throws InterruptedException { while (true) { synchronized (this) { while (queue.isEmpty()) { wait(); } int value = queue.poll(); System.out.println("Consumed: " + value); notify(); Thread.sleep(1000); } } } } public class WaitNotifyExample { public static void main(String[] args) { ProducerConsumer pc = new ProducerConsumer(5); Thread producer = new Thread(() -> { try { pc.produce(); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread consumer = new Thread(() -> { try { pc.consume(); } catch (InterruptedException e) { e.printStackTrace(); } }); producer.start(); consumer.start(); } }
在上述示例中,我们实现了一个生产者-消费者问题。生产者线程和消费者线程通过共享队列进行通信。我们使用wait()
和notify()
方法来同步生产者和消费者的执行。
java.util.concurrent
包中的工具类java.util.concurrent
包提供了许多工具类,可以用于线程间的通信。这些类包括 Semaphore
、CountDownLatch
、CyclicBarrier
、Exchanger
、BlockingQueue
等。这些类提供了高级的同步和通信机制,可以简化多线程编程。
下面是使用 BlockingQueue
实现生产者-消费者问题的示例:
import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; class Producer implements Runnable { private final BlockingQueue<Integer> sharedQueue; public Producer(BlockingQueue<Integer> sharedQueue) { this.sharedQueue = sharedQueue; } @Override public void run() { for (int i = 0; i < 10; i++) { try { System.out.println("Produced: " + i); sharedQueue.put(i); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Consumer implements Runnable { private final BlockingQueue<Integer> sharedQueue; public Consumer(BlockingQueue<Integer> sharedQueue) { this.sharedQueue = sharedQueue; } @Override public void run() { while (true) { try { int item = sharedQueue.take(); System.out.println("Consumed: " + item); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class BlockingQueueExample { public static void main(String[] args) { BlockingQueue<Integer> sharedQueue = new LinkedBlockingQueue<>(); Thread producer = new Thread(new Producer(sharedQueue)); Thread consumer = new Thread(new Consumer(sharedQueue)); producer.start(); consumer.start(); } }
在这个示例中,我们使用 BlockingQueue
实现生产者-消费者问题。BlockingQueue
是一个线程安全的队列,它提供了阻塞的 put()
和 take()
方法,可以在队列满或空时阻塞生产者或消费者线程。这样,我们不再需要显式地使用 wait()
和 notify()
方法来同步线程。
在本章节中,我们讨论了Java多线程与并发的“5.4 线程间通信”。我们了解了如何使用共享变量、wait()
、notify()
和notifyAll()
以及java.util.concurrent
包中的工具类实现线程间通信。
线程间通信是多线程编程中的关键概念,它可以帮助我们解决复杂的同步和协作问题。掌握这些方法对于编写高效的并发程序至关重要。
请务必多加实践,以便更好地掌握这些知识点。祝你学习顺利!