最近面試中遇到Java線程的三個同步工具類的問題,沒有複習一時還真想不起來,學多線程的時候也沒有仔細學習同步工具類,現在更是忘了。因此我又重溫了一遍感覺挺高深的,為了備忘就整理了一下寫篇文章,供大家參考。 apache php mysql
Java為我們提供了三個同步工具類別:
一組執行緒互相等待至某個狀態,而這組執行緒再同時執行。
更好控制執行緒之間的通訊問題~
一、 CountDownLatch1.1CountDownLatch簡介允許一個或多個執行緒一直等待#簡單來說:CountDownLatch是一個同步的輔助類,
- A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes
,直到其它執行緒完成它們的操作。 它常用的API其實就兩個:
await()和countDown()
使用說明:
使計數器count減1。 當count減到0時,所有在等待的執行緒都會被釋放
,如果count值為0了(其他執行緒的任務都完成了),那就可以繼續執行。
import java.util.concurrent.CountDownLatch; public class Test { public static void main(String[] args) { final CountDownLatch countDownLatch = new CountDownLatch(5); System.out.println("现在6点下班了....."); // 3y线程启动 new Thread(new Runnable() { @Override public void run() { try { // 这里调用的是await()不是wait() countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("...其他的5个员工走光了,3y终于可以走了"); } }).start(); // 其他员工线程启动 for (int i = 0; i < 5; i++) { new Thread(new Runnable() { @Override public void run() { System.out.println("员工xxxx下班了"); countDownLatch.countDown(); } }).start(); } } }
輸出結果:
再寫範例:3y現在負責倉庫模組功能,但是能力太差了,寫得很慢,
別的員工都需要等3y寫好了才能繼續往下寫。import java.util.concurrent.CountDownLatch;
public class Test {
public static void main(String[] args) {
final CountDownLatch countDownLatch = new CountDownLatch(1);
// 3y线程启动
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("3y终于写完了");
countDownLatch.countDown();
}
}).start();
// 其他员工线程启动
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("其他员工需要等待3y");
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("3y终于写完了,其他员工可以开始了!");
}
}).start();
}
}
}
輸出結果:
二、CyclicBarrier
到達某個公共屏障點#A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of 是詞called
簡單來說:CyclicBarrier允許一組線程互相等待,直到- cyclic
because it can be re-used after the waiting threads are released.
。叫做cyclic是因為當所有等待執行緒都被釋放以後,CyclicBarrier可以被重用(對比於CountDownLatch是不能重用的)使用說明:
,CyclicBarrier注重的是:當線程到達某個狀態後,暫停下來等待其他線程,所有線程都到達以後,繼續執行。
,約定等到互相見面的時候就發一條朋友圈。 import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class Test {
public static void main(String[] args) {
final CyclicBarrier CyclicBarrier = new CyclicBarrier(2);
for (int i = 0; i < 2; i++) {
new Thread(() -> {
String name = Thread.currentThread().getName();
if (name.equals("Thread-0")) {
name = "3y";
} else {
name = "女朋友";
}
System.out.println(name + "到了体育西");
try {
// 两个人都要到体育西才能发朋友圈
CyclicBarrier.await();
// 他俩到达了体育西,看见了对方发了一条朋友圈:
System.out.println("跟" + name + "去夜上海吃东西~");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
測試結果:
玩了一天以後,
各自回到家裡,3y和女朋友約定各自洗澡完再聊天import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class Test {
public static void main(String[] args) {
final CyclicBarrier CyclicBarrier = new CyclicBarrier(2);
for (int i = 0; i < 2; i++) {
new Thread(() -> {
String name = Thread.currentThread().getName();
if (name.equals("Thread-0")) {
name = "3y";
} else {
name = "女朋友";
}
System.out.println(name + "到了体育西");
try {
// 两个人都要到体育西才能发朋友圈
CyclicBarrier.await();
// 他俩到达了体育西,看见了对方发了一条朋友圈:
System.out.println("跟" + name + "去夜上海吃东西~");
// 回家
CyclicBarrier.await();
System.out.println(name + "洗澡");
// 洗澡完之后一起聊天
CyclicBarrier.await();
System.out.println("一起聊天");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
測試結果:
Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource.
A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each {@link #acquire} blocks if necessary until a permit is available, and then takes it. Each {@link #release} adds a permit,potentially releasing a blocking acquirer.However, no actual permit objects are used; the {@code Semaphore} just
keeps a count of the number available and acts accordingly.
Semaphore(信号量)实际上就是可以控制同时访问的线程个数,它维护了一组"许可证"。
当调用acquire()
方法时,会消费一个许可证。如果没有许可证了,会阻塞起来
当调用release()
方法时,会添加一个许可证。
这些"许可证"的个数其实就是一个count变量罢了~
3y女朋友开了一间卖酸奶的小店,小店一次只能容纳5个顾客挑选购买,超过5个就需要排队啦~~~
import java.util.concurrent.Semaphore; public class Test { public static void main(String[] args) { // 假设有50个同时来到酸奶店门口 int nums = 50; // 酸奶店只能容纳10个人同时挑选酸奶 Semaphore semaphore = new Semaphore(10); for (int i = 0; i < nums; i++) { int finalI = i; new Thread(() -> { try { // 有"号"的才能进酸奶店挑选购买 semaphore.acquire(); System.out.println("顾客" + finalI + "在挑选商品,购买..."); // 假设挑选了xx长时间,购买了 Thread.sleep(1000); // 归还一个许可,后边的就可以进来购买了 System.out.println("顾客" + finalI + "购买完毕了..."); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } } }
输出结果:
反正每次只能5个客户同时进酸奶小店购买挑选。
总结:本文简单的介绍了一下Java多线程的三个同步工具类的用处以及如何用,要深入还得看源码或者查阅其他的资料。如果文章有错的地方欢迎指正,大家互相交流。
相关文章:
相关视频:
以上是Java線程的三個同步工具類知識點的匯總,收藏備忘的詳細內容。更多資訊請關注PHP中文網其他相關文章!