在Java中,线程间的通信主要涉及到线程间的数据交换和协调。以下是几种常见的线程间通信方式:
-
共享对象 :
线程可以通过共享对象的实例变量或方法参数来进行通信。这种方式需要特别注意线程安全,通常需要同步代码块或使用锁来避免并发问题。
javapublic class SharedObject { private int sharedValue; public void setValue(int value) { // 线程安全写入 synchronized (this) { sharedValue = value; } } public int getValue() { // 线程安全读取 synchronized (this) { return sharedValue; } } }
-
wait() 和 notify()/notifyAll() :
Java线程有
wait()
、notify()
和notifyAll()
方法,它们可以用来在线程间进行阻塞和唤醒操作,实现线程间的协调。javapublic class Communication { private boolean ready = false; public synchronized void waitForSignal() throws InterruptedException { while (!ready) { wait(); // 等待信号 } // 执行后续操作 } public synchronized void sendSignal() { ready = true; notifyAll(); // 唤醒所有等待的线程 } }
-
volatile 关键字 :
使用
volatile
关键字声明的变量可以确保所有线程看到的是最新的值,因为对volatile
变量的读写操作不会被缓存在寄存器或其他处理器内部的缓存中。javapublic class VolatileCommunication { private volatile boolean flag = false; public void setFlag() { flag = true; } public void checkFlag() { while (!flag) { // 循环检查标志位 } } }
-
Lock 和 Condition :
java.util.concurrent.locks.Lock
接口和java.util.concurrent.locks.Condition
接口提供了更高级的锁和条件对象,可以实现复杂的线程间通信。javaLock lock = new ReentrantLock(); Condition condition = lock.newCondition(); public void awaitCondition() throws InterruptedException { lock.lock(); try { while (!某个条件) { condition.await(); // 等待条件成立 } // 执行后续操作 } finally { lock.unlock(); } } public void signalCondition() { lock.lock(); try { 某个条件 = true; condition.signalAll(); // 唤醒所有等待的线程 } finally { lock.unlock(); } }
-
Exchanger :
Exchanger
是一个可以在两个线程间交换数据的同步辅助类。当两个线程分别调用exchange()
方法时,它们可以交换数据。javaExchanger<String> exchanger = new Exchanger<>(); new Thread(() -> { String fromFirst = "Hello"; try { String fromSecond = exchanger.exchange(fromFirst); System.out.println("Received: " + fromSecond); } catch (InterruptedException e) { e.printStackTrace(); } }).start();
-
BlockingQueue :
java.util.concurrent.BlockingQueue
是一个线程安全的队列,可以用于生产者-消费者模式中的线程间通信。javaBlockingQueue<String> queue = new LinkedBlockingQueue<>(); new Thread(() -> { try { // 生产者线程 queue.put("Item"); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); new Thread(() -> { try { // 消费者线程 String item = queue.take(); System.out.println("Removed: " + item); } catch (InterruptedException e) { e.printStackTrace(); } }).start();
-
Callable 和 Future :
Callable
任务可以返回结果,并且可以抛出异常。通过Future
对象,线程可以获取Callable
任务的结果。javaExecutorService executor = Executors.newFixedThreadPool(2); Future<Integer> future = executor.submit(() -> { // 执行任务并返回结果 return 42; }); try { Integer result = future.get(); // 等待任务完成并获取结果 System.out.println("Task result: " + result); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } finally { executor.shutdown(); }
这些线程间通信的方式各有特点和适用场景,开发者可以根据具体的应用需求选择合适的通信机制。