关于人工智能:55-Java并发工具类如CountDownLatchCyclicBarrier等

6次阅读

共计 4146 个字符,预计需要花费 11 分钟才能阅读完成。

5.5.1 CountDownLatch

CountDownLatch是一个同步辅助类,它容许一个或多个线程期待,直到其余线程实现一组操作。CountDownLatch有一个计数器,当计数器减为 0 时,期待的线程将被唤醒。计数器只能缩小,不能减少。

示例:应用 CountDownLatch 期待所有线程实现工作

假如咱们有一个工作须要三个子工作实现,咱们能够应用 CountDownLatch 来期待所有子工作实现。

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {public static void main(String[] args) throws InterruptedException {CountDownLatch latch = new CountDownLatch(3);

        for (int i = 1; i <= 3; i++) {
            final int taskNumber = i;
            new Thread(() -> {System.out.println("Task" + taskNumber + "started");
                try {Thread.sleep(1000 * taskNumber);
                } catch (InterruptedException e) {e.printStackTrace();
                }
                System.out.println("Task" + taskNumber + "completed");
                latch.countDown();}).start();}

        System.out.println("Waiting for all tasks to complete...");
        latch.await();
        System.out.println("All tasks completed");
    }
}

在这个示例中,咱们创立了一个 CountDownLatch 并设置初始计数器为 3。每个子工作实现后,调用 latch.countDown() 缩小计数器。主线程调用 latch.await() 期待所有子工作实现。

5.5.2 CyclicBarrier

CyclicBarrier是一个同步辅助类,它容许一组线程互相期待,直到所有线程都筹备好继续执行。当所有线程都达到屏障点时,屏障将关上。CyclicBarrier能够重复使用。

示例:应用 CyclicBarrier 同步多个线程

假如咱们有三个线程须要在某个点同步,咱们能够应用 CyclicBarrier 实现这个目标。

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {public static void main(String[] args) {CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All threads are ready to proceed"));

        for (int i = 1; i <= 3; i++) {
            final int taskNumber = i;
            new Thread(() -> {System.out.println("Task" + taskNumber + "is ready");
                try {barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();
                }
                System.out.println("Task" + taskNumber + "is proceeding");
            }).start();}
    }
}

在这个示例中,咱们创立了一个 CyclicBarrier 并设置参与者数量为 3。每个线程在筹备好继续执行之前调用barrier.await()。当所有线程都筹备好时,屏障将关上,所有线程将继续执行。

5.5.3 Semaphore

Semaphore是一个计数信号量,它保护了一个许可集。线程能够申请许可,如果有可用的许可,线程将取得许可并继续执行。否则,线程将阻塞,直到有可用的许可。许可能够由任何线程开释。Semaphore可用于实现资源池、限度并发拜访等。

示例:应用 Semaphore 限度并发拜访

假如咱们有一个只能同时解决三个申请的服务器,咱们能够应用 Semaphore 来实现并发拜访限度。

import java.util.concurrent.Semaphore;

public class SemaphoreExample {public static void main(String[] args) {Semaphore semaphore = new Semaphore(3);

        for (int i = 1; i <= 10; i++)            final int clientNumber = i;
            new Thread(() -> {
                try {System.out.println("Client" + clientNumber + "is trying to connect");
                    semaphore.acquire();
                    System.out.println("Client" + clientNumber + "is connected");
                    Thread.sleep(2000);
                    System.out.println("Client" + clientNumber + "is disconnected");
                } catch (InterruptedException e) {e.printStackTrace();
                } finally {semaphore.release();
                }
            }).start();}
    }
}

在这个示例中,咱们创立了一个 Semaphore 并设置初始许可数量为 3。每个客户端线程在连贯服务器之前调用 semaphore.acquire() 申请许可。当许可可用时,线程将取得许可并继续执行。线程实现后,调用 semaphore.release() 开释许可。

5.5.4 Exchanger

Exchanger是一个同步辅助类,它容许两个线程在一个临界点替换数据。当两个线程都达到替换点时,它们将替换数据。Exchanger能够用于遗传算法、管道设计等。

示例:应用 Exchanger 替换数据

假如咱们有两个线程,一个生成数据,另一个解决数据。咱们能够应用 Exchanger 在这两个线程之间替换数据。

import java.util.concurrent.Exchanger;

public class ExchangerExample {public static void main(String[] args) {Exchanger<String> exchanger = new Exchanger<>();

        new Thread(() -> {
            try {
                String data = "Data from producer";
                System.out.println("Producer is sending:" + data);
                String receivedData = exchanger.exchange(data);
                System.out.println("Producer received:" + receivedData);
            } catch (InterruptedException e) {e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            try {
                String data = "Data from consumer";
                System.out.println("Consumer is sending:" + data);
                String receivedData = exchanger.exchange(data);
                System.out.println("Consumer received:" + receivedData);
            } catch (InterruptedException e) {e.printStackTrace();
            }
        }).start();}
}

在这个示例中,咱们创立了一个Exchanger。生产者和消费者线程在替换数据前调用exchanger.exchange(data)。当两个线程都达到替换点时,它们将替换数据。

5.5.5 Phaser

Phaser是一个灵便的同步辅助类,它容许一组线程互相期待,直到所有线程都筹备好继续执行。与 CyclicBarrier 相似,但 Phaser 更加灵便,能够动静调整参与者数量和反对多个阶段。

示例:应用 Phaser 同步多个线程

假如咱们有三个线程须要在某个点同步,咱们能够应用 Phaser 实现这个目标。

import java.util.concurrent.Phaser;

public class PhaserExample {public static void main(String[] args) {Phaser phaser = new Phaser(3);

        for (int i = 1; i <= 3; i++) {
            final int taskNumber = i;
            new Thread(() -> {System.out.println("Task" + taskNumber + "is ready");
                phaser.arriveAndAwaitAdvance();
                System.out.println("Task" + taskNumber + "is proceeding");
            }).start();}
    }
}

在这个示例中,咱们创立了一个 Phaser 并设置参与者数量为 3。每个线程在筹备好继续执行之前调用phaser.arriveAndAwaitAdvance()。当所有线程都筹备好时,屏障将关上,所有线程将继续执行。

这些并发工具类为 Java 多线程编程提供了弱小的反对,帮忙咱们更轻松地实现各种同步和并发场景。心愿这些示例能帮忙你了解并把握这些工具类的用法。
举荐浏览:

https://mp.weixin.qq.com/s/dV2JzXfgjDdCmWRmE0glDA

https://mp.weixin.qq.com/s/an83QZOWXHqll3SGPYTL5g

正文完
 0