信号
当使用文件系统时需要限制线程数时,通常会使用信号量。通过计数器控制对文件或其他共享资源的访问。如果其值大于零,则允许访问,但同时计数器会减少。
在计数器归零的那一刻,当前线程将被阻塞,直到资源被另一个线程释放。必须通过构造函数设置权限参数的数量。
您需要单独选择此参数,具体取决于您的计算机或笔记本电脑的功率。
public class Main {
public static void main(String[] args) {
Semaphore sem = new Semaphore(1);
CommonResource res = new CommonResource();
new Thread(new MyThread(res, sem, "MyThread_1")).start();
new Thread(new MyThread(res, sem, "MyThread_2")).start();
new Thread(new MyThread(res, sem, "MyThread_3")).start();
}
}
class CommonResource {
int value = 0;
}
class MyThread implements Runnable {
CommonResource commonResource;
Semaphore semaphore;
String name;
MyThread(CommonResource commonResource, Semaphore sem, String name) {
this.commonResource = commonResource;
this.semaphore = sem;
this.name = name;
}
public void run() {
try {
System.out.println(name + "waiting permission");
semaphore.acquire();
commonResource.value = 1;
for (int i = 1; i < 7; i++) {
System.out.println(this.name + ": " + commonResource.value);
commonResource.value++;
Thread.sleep(150);
}
} catch (InterruptedException e) {
System.out.println(e.getMessage() + " " + name);
Thread.currentThread().interrupt();
}
System.out.println(name + "releases permission");
semaphore.release();
}
}
CountDownLatch 等
CountDownLatch - 允许多个线程等待,直到对其他线程执行的一定数量的操作完成。一个例子是应用程序的安装:直到您接受使用条款,它才会开始,直到您选择一个文件夹来安装新程序,等等。为此有一个特殊的countDown()方法- 此方法将倒计时计数器减一。
一旦计数归零,await 中的所有等待线程将继续其工作,并且所有后续的 await 调用将不等待而通过。递减计数器是一次性计数器,不能重置。
CyclicBarrier - 用于在某一点同步给定数量的线程。当 N 个线程调用 await(...) 方法并阻塞时达到屏障。之后,计数器被重置为原来的值,等待的线程将被释放。此外,如果需要,可以在取消阻塞线程和重置计数器之前运行自定义代码。为此,通过构造函数传递一个实现了Runnable接口的对象。
Exchanger<V> — Exchanger类用于线程之间的数据交换。它是类型化的,类型是线程需要交换的数据类型。
使用此类唯一的exchange()方法交换数据:
V exchange(V x) throws InterruptedException
V exchange(V x, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException
x 参数表示要交换的数据缓冲区。该方法的第二种形式还定义了超时参数timeout 和unit,即用于超时参数的时间单位类型。
Phaser类允许您同步表示整体操作执行中的单个阶段或阶段的线程。Phaser定义了一个同步对象,它等待某个阶段完成。Phaser然后进入下一阶段或阶段并等待它再次完成。
使用Phaser类时,通常首先创建其对象。接下来,我们需要注册所有参与者。要为每个参与者注册,调用register()方法,或者您可以通过将所需数量的参与者传递给Phaser构造函数来不使用此方法。
然后每个参与者执行一组特定的动作,这些动作构成了这个阶段。Phaser同步器等待所有参与者完成阶段的执行。要通知同步器该阶段已结束,参与者必须调用arrive()或arriveAndAwaitAdvance()方法。然后同步器进入下一阶段。
GO TO FULL VERSION