在Java中,有多种方法可以实现多线程之间的通信和协作,以下是几种常见的方式:
- 使用Object的wait(), notify() 和 notifyAll() 方法:这些方法用于协调多个线程对共享资源的访问。在一个线程调用对象的wait()方法时,它会释放对象的锁,让其他线程可以获取该对象的锁并访问共享资源。当其他线程调用该对象的notify()或notifyAll()方法时,正在等待的线程会被唤醒。需要注意的是,这些方法必须在同步块或者同步方法中被调用,否则会抛出IllegalMonitorStateException。
public class SharedObject {
private String message;
public synchronized void write(String message) {
while (this.message != null) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
this.message = message;
notifyAll();
}
public synchronized String read() {
while (this.message == null) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
String message = this.message;
this.message = null;
notifyAll();
return message;
}
}
public class WriterThread extends Thread {
private SharedObject sharedObject;
private String message;
public WriterThread(SharedObject sharedObject, String message) {
this.sharedObject = sharedObject;
this.message = message;
}
@Override
public void run() {
sharedObject.write(message);
}
}
public class ReaderThread extends Thread {
private SharedObject sharedObject;
public ReaderThread(SharedObject sharedObject) {
this.sharedObject = sharedObject;
}
@Override
public void run() {
String message = sharedObject.read();
System.out.println("Read message: " + message);
}
}
public class Main {
public static void main(String[] args) {
SharedObject sharedObject = new SharedObject();
WriterThread writerThread = new WriterThread(sharedObject, "Hello, World!");
ReaderThread readerThread = new ReaderThread(sharedObject);
writerThread.start();
readerThread.start();
}
}
- 使用java.util.concurrent包中的锁:Java的并发库提供了多种锁,如ReentrantLock、ReentrantReadWriteLock等,这些锁比使用Object的wait/notify机制更灵活。
- 使用java.util.concurrent包中的并发集合:Java的并发库提供了一些并发集合,如ConcurrentHashMap、CopyOnWriteArrayList等,这些集合是为了解决线程安全问题而设计的。
- 使用java.util.concurrent包中的Future和Callable:Callable允许你返回一个结果,并且可以抛出一个受检查的异常。Future允许你检查计算是否完成,如果未完成,则阻塞直到完成。
- 使用java.util.concurrent包中的Semaphore和CyclicBarrier:Semaphore是一个计数信号量,用于保护一段代码或资源,防止同一时间多个线程访问。CyclicBarrier是一个同步辅助工具,它允许一组线程互相等待,直到所有线程都到达一个公共屏障点。
- 使用java.util.concurrent包中的CountDownLatch:CountDownLatch是一个同步辅助工具,它允许一个或多个线程等待,直到在其他线程执行的操作完成。
- 使用java.util.concurrent包中的Exchanger:Exchanger允许两个线程在某个点交换彼此的数据。
- 使用java.util.concurrent包中的SynchronousQueue:SynchronousQueue是一个没有容量的阻塞队列。每个插入操作必须等待一个相应的删除操作,反之亦然。