📅  最后修改于: 2023-12-03 15:02:03.193000             🧑  作者: Mango
在Java中,线程间通信是多线程编程中的一个重要概念。当多个线程并发执行时,可能会需要线程间通信来实现线程间的同步和协作。
Java提供了多种机制来实现线程间通信,主要包括:
互斥锁是最基本的线程同步机制。在Java中,可以使用synchronized
关键字来实现互斥锁。
使用synchronized
关键字的时候,需要指定一个共享对象,称为“锁对象”。在临界区代码执行时,线程会尝试获取锁对象的锁,若锁已被其他线程占用,则会被阻塞等待,直到锁被释放。
示例代码:
public class MyThread extends Thread {
private Object lock;
public MyThread(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
// 这里是临界区
// ...
}
}
}
条件变量是一种用于线程间通信的机制。在Java中,可以使用wait()
和notify()
方法来实现条件变量。
当一个线程调用了wait()
方法之后,它会释放当前持有的锁对象,并且进入等待状态,直到其他线程调用了相同锁对象的notify()
或notifyAll()
方法,唤醒等待线程。
示例代码:
public class MyThread extends Thread {
private Object lock;
public MyThread(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
try {
lock.wait();
// 线程被唤醒后,执行这里的代码
// ...
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
管道是一种用于进程间通信的机制,Java中的管道可以实现线程间通信。管道由两个管道流组成,一个用于输入,一个用于输出。
示例代码:
public class MyThread1 extends Thread {
private PipedOutputStream outputStream;
public MyThread1(PipedOutputStream outputStream) {
this.outputStream = outputStream;
}
@Override
public void run() {
try {
outputStream.write("Hello, world".getBytes());
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class MyThread2 extends Thread {
private PipedInputStream inputStream;
public MyThread2(PipedInputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public void run() {
try {
byte[] buffer = new byte[1024];
int len = inputStream.read(buffer);
System.out.println(new String(buffer, 0, len));
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Test {
public static void main(String[] args) {
try {
PipedOutputStream outputStream = new PipedOutputStream();
PipedInputStream inputStream = new PipedInputStream(outputStream);
MyThread1 thread1 = new MyThread1(outputStream);
MyThread2 thread2 = new MyThread2(inputStream);
thread1.start();
thread2.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
信号量是一种用于控制资源访问权限的机制。在Java中,可以使用Semaphore
类来实现信号量。
Semaphore
类提供了两个方法:acquire()
和release()
。当一个线程调用acquire()
方法时,它会尝试获取信号量,如果当前有可用资源,则会获取成功。如果没有可用资源,则会被阻塞等待,直到其他线程释放资源。当一个线程调用release()
方法时,它会释放一个资源,并唤醒一个正在等待资源的线程。
示例代码:
public class MyThread extends Thread {
private Semaphore semaphore;
public MyThread(Semaphore semaphore) {
this.semaphore = semaphore;
}
@Override
public void run() {
try {
semaphore.acquire();
// 在这里执行临界区代码
// ...
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
读写锁是一种特殊的锁,适用于读操作远远多于写操作的情况。在Java中,可以使用ReentrantReadWriteLock
类来实现读写锁。
ReentrantReadWriteLock
类提供了两个锁对象:读锁和写锁。当一个线程获取读锁时,如果当前没有写锁,那么它可以获取读锁并继续执行。当多个线程同时获取读锁时,它们可以同时执行,不会互相影响。当一个线程获取写锁时,它必须等待所有读锁释放完毕,并且当前没有其他线程持有写锁,才能获取写锁并继续执行。
示例代码:
public class MyThread extends Thread {
private ReentrantReadWriteLock lock;
public MyThread(ReentrantReadWriteLock lock) {
this.lock = lock;
}
@Override
public void run() {
lock.readLock().lock();
// 在这里执行读操作
lock.readLock().unlock();
lock.writeLock().lock();
// 在这里执行写操作
lock.writeLock().unlock();
}
}
同步队列是一种用于线程间通信的机制。在Java中,可以使用SynchronousQueue
类来实现同步队列。
SynchronousQueue
类是一个没有容量的队列。当一个线程尝试向队列中添加元素时,如果当前没有其他线程正在等待获取元素,并且没有其他元素在队列中等待,那么该线程会被阻塞等待,直到另一个线程尝试从队列中获取元素。当一个线程尝试从队列中获取元素时,如果当前没有其他线程正在等待添加元素,并且有元素在队列中等待获取,那么该线程会获取到该元素并继续执行。
示例代码:
public class MyThread1 extends Thread {
private SynchronousQueue<Integer> queue;
public MyThread1(SynchronousQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
queue.put(123);
// 将123添加到队列中,会被阻塞等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class MyThread2 extends Thread {
private SynchronousQueue<Integer> queue;
public MyThread2(SynchronousQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
Integer result = queue.take();
// 从队列中获取元素,如果没有元素在队列中等待,则会被阻塞等待
System.out.println(result);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Test {
public static void main(String[] args) {
SynchronousQueue<Integer> queue = new SynchronousQueue<>();
MyThread1 thread1 = new MyThread1(queue);
MyThread2 thread2 = new MyThread2(queue);
thread1.start();
thread2.start();
}
}
等待通知机制是一种用于线程间通信的机制。在Java中,可以使用wait()
和notify()
方法来实现等待通知机制。
当一个线程调用了wait()
方法之后,它会释放当前持有的锁对象,并且进入等待状态,直到其他线程调用了相同锁对象的notify()
或notifyAll()
方法,唤醒等待线程。当一个线程调用了notify()
方法时,它会唤醒一个正在等待这个锁对象的线程,并且释放锁对象。
示例代码:
public class MyThread extends Thread {
private Object lock;
public MyThread(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
try {
lock.wait();
// 线程被唤醒后,执行这里的代码
// ...
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Test {
public static void main(String[] args) {
Object lock = new Object();
MyThread thread = new MyThread(lock);
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock) {
lock.notify();
}
}
}
以上是Java中的线程间通信的介绍,提供了多种实现方式,可以根据具体的业务需求来选用合适的机制。