欢迎大家来到IT世界,在知识的湖畔探索吧!
多线程是计算机科学中非常重要的一个概念,它可以提高程序的执行效率,充分利用计算机的资源。在 Java 编程中,多线程也很常见,Java 提供了丰富的多线程库支持。但是多线程也存在一些困难,如线程间的通讯、协作等问题。本文将深入探讨如何让线程之间默契无间地通讯和协作,帮助读者更好地理解和应用 Java 多线程。
摘要
本文将介绍 Java 多线程中的线程通讯和协作技巧。首先讨论了线程通讯的基本原理,包括 wait(), notify() 和 notifyAll() 等方法的使用。然后,介绍了线程协作的概念和常见技巧,如使用 Semaphore、CountDownLatch 和 CyclicBarrier 等工具类。最后,通过代码实现多个线程之间的通讯和协作,并提供了测试用例。
线程通讯
线程通讯是指多个线程之间的信息交换和协作。在 Java 中,线程通讯主要通过共享对象的方式实现。多个线程共享一个对象,通过该对象的方法实现线程之间的通讯。
wait() 和 notify()
wait() 和 notify() 是 Java 中实现线程通讯的两个重要方法。它们都属于 Object 类,任何一个 Java 对象都可以调用这两个方法。其基本思想是在一个共享对象上进行操作,使线程挂起或唤醒。
wait() 方法的作用是使当前线程进入等待状态,直到其他线程调用了该对象的 notify() 或 notifyAll() 方法唤醒它。
public synchronized void wait() throws InterruptedException;
public synchronized void wait(long timeout) throws InterruptedException;
public synchronized void wait(long timeout, int nanos) throws InterruptedException;
欢迎大家来到IT世界,在知识的湖畔探索吧!
notify() 方法的作用是唤醒一个等待该对象的线程。
欢迎大家来到IT世界,在知识的湖畔探索吧!public synchronized void notify();
notifyAll() 方法的作用是唤醒所有等待该对象的线程。
public synchronized void notifyAll();
代码示例
下面是一个经典的生产者-消费者模型,使用 wait() 和 notify() 方法实现线程通讯。
生产者线程:
欢迎大家来到IT世界,在知识的湖畔探索吧!class Producer implements Runnable {
private Queue<String> queue;
private int maxSize;
private int i = 0;
public Producer(Queue<String> queue, int maxSize) {
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.size() == maxSize) { // 当队列满了,生产者线程等待
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.offer("message" + (++i));
System.out.println("produce: " + i);
queue.notifyAll(); // 生产者线程生产完消息,唤醒所有等待队列的线程
}
}
}
}
消费者线程:
class Consumer implements Runnable {
private Queue<String> queue;
public Consumer(Queue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) { // 当队列为空,消费者线程等待
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String message = queue.poll();
System.out.println("consume: " + message);
queue.notifyAll(); // 消费者线程消费完消息,唤醒所有等待队列的线程
}
}
}
}
测试代码:
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
int maxSize = 5;
Thread producerThread = new Thread(new Producer(queue, maxSize));
Thread consumerThread = new Thread(new Consumer(queue));
producerThread.start();
consumerThread.start();
}
测试结果如下:
线程协作
线程协作是指多个线程之间相互协作,共同完成一个任务。在 Java 中,线程协作主要通过工具类实现。常见的工具类有 Semaphore、CountDownLatch 和 CyclicBarrier 等。
Semaphore
Semaphore 是 Java 中一个基于计数器的同步工具类,用来控制同时访问某个资源的线程数量。它通过 acquire() 和 release() 方法来协调线程的运行。
public Semaphore(int permits);
public Semaphore(int permits, boolean fair);
public void acquire() throws InterruptedException;
public void acquire(int permits) throws InterruptedException;
public void release();
public void release(int permits);
其中 permits 表示资源的数量,fair 表示使用公平或非公平的机制。当 permits 大于 1 时,表示多线程可以同时访问资源。
CountDownLatch
CountDownLatch 是 Java 中一个基于计数器的同步工具类,用来协调多个线程之间的运行。它通过 await() 和 countDown() 方法来协调线程的运行。
public CountDownLatch(int count);
public void await() throws InterruptedException;
public boolean await(long timeout, TimeUnit unit) throws InterruptedException;
public void countDown();
public long getCount();
其中 count 表示需要完成的任务数量。当 count 减为 0 时,所有的线程将被唤醒。
CyclicBarrier
CyclicBarrier 是 Java 中一个同步工具类,用来协调多个线程之间的运行。它允许多个线程在某个屏障处阻塞,直到所有线程都到达该屏障后才能继续执行。
public CyclicBarrier(int parties);
public CyclicBarrier(int parties, Runnable barrierAction);
public void await() throws InterruptedException, BrokenBarrierException;
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException;
其中 parties 表示需要等待的线程数量。当所有的线程都到达该屏障后,可以选择执行 barrierAction。当最后一个线程到达该屏障后,所有的线程将被唤醒。
代码示例
下面是一个使用 Semaphore 实现并发控制的示例。
class SemaphoreDemo implements Runnable {
private Semaphore semaphore;
private int n;
public SemaphoreDemo(Semaphore semaphore, int n) {
this.semaphore = semaphore;
this.n = n;
}
@Override
public void run() {
try {
semaphore.acquire(); // 获取一个 permit
for (int i = 0; i < n; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放一个 permit
}
}
}
测试代码:
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2);
int n = 5;
for (int i = 0; i < 5; i++) {
new Thread(new SemaphoreDemo(semaphore, n)).start(); // 同时运行 2 个线程
}
}
测试结果如下:
小结
本文介绍了 Java 多线程中的线程通讯和协作技巧。其中,线程通讯主要通过 wait() 和 notify() 方法实现,线程协作主要通过 Semaphore、CountDownLatch 和 CyclicBarrier 等工具类实现。通过代码示例,读者可以更好地理解和应用 Java 多线程。
作者:我崽不熬夜
链接:https://juejin.cn/post/7273433799668711487
来源:稀土掘金
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/35876.html