文章目錄
- 前言
- ReentranLock
- CountDownLatch
- CyclicBarrier
- Phaser
- ReadWriteLock
- Semaphore
- Exchanger
- LockSupport
- 總結
前言
??JUC即java.util.concurrent包,這個包下面提供很多用于保證多執行緒安全的類,比如atomic包下面的原子類、locks包下面和鎖相關的類以及其他類,在這篇文章中,我們將講解JUC下一些常用的類的基本使用,
ReentranLock
public static void testReentrantLock() {
Lock lock = new ReentrantLock();
new Thread(() -> {
try {
lock.lock();
Sleep.sleep(5);
System.out.println("t1 end...");
} finally {
lock.unlock();
}
}).start();
Sleep.sleep(1);
new Thread(() -> {
if (lock.tryLock()) {
try {
System.out.println("tryLock succ");
} finally {
lock.unlock();
}
} else {
System.out.println("tryLock fail");
}
}).start();
}
??ReentranLock需要手動呼叫lock()方法進行加鎖,并且需要在finally塊中呼叫unlock()方法釋放鎖,防止發生例外時出現死鎖,除了lock()方法之外,ReentranLock還提供了tryLock()方法嘗試獲取鎖,如果獲取失敗可以繼續執行其他的操作而不用一種阻塞等待,
CountDownLatch
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(1);
new Thread(() -> {
Sleep.sleep(2);
latch.countDown();
}).start();
System.out.println("執行緒開始");
latch.await();
System.out.println("2s之后,countDown");
}
??一個執行緒A可使用CountDownLatch.await()方法阻塞等待,其他執行緒可呼叫CountDownLatch.countDown()方法使CountDownLatch數值減1,當CountDownLatch數值為0的時候,執行緒A可以繼續往下執行,
CyclicBarrier
public void testCycleBarrie() {
CyclicBarrier barrier = new CyclicBarrier(5, () -> {
System.out.println("坐滿了,發車!");
});
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + "到達");
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}, "乘客" + i).start();
}
}
??以上代碼模擬了這樣一個場景,有一個輛客車,需要坐滿5個人的時候才可以發車,客車出發后,下一輛車同樣需要坐滿5個人才可以發車,周而復始,
Phaser
public class TestPhaser {
static Random r = new Random();
static MarriagePhaser phaser = new MarriagePhaser();
public static void main(String[] args) throws InterruptedException {
phaser.bulkRegister(7);
for (int i = 0; i < 5; i++) {
new Person("person" + i).start();
}
new Person("新郎").start();
new Person("新娘").start();
}
static class Person extends Thread {
String name;
public Person(String name) {
this.name = name;
}
public void arrive() throws InterruptedException {
Thread.sleep(r.nextInt(1000));
System.out.printf("%s 到達現場!\n", name);
phaser.arriveAndAwaitAdvance();
}
public void eat() throws InterruptedException {
Thread.sleep(r.nextInt(1000));
System.out.printf("%s 吃完!\n", name);
phaser.arriveAndAwaitAdvance();
}
public void leave() throws InterruptedException {
if (name.equals("新郎") || name.equals("新娘")) {
phaser.arriveAndAwaitAdvance();
} else {
Thread.sleep(r.nextInt(1000));
System.out.printf("%s 離開!\n", name);
phaser.arriveAndAwaitAdvance();
}
}
private void hug() throws InterruptedException {
if (name.equals("新郎") || name.equals("新娘")) {
Thread.sleep(r.nextInt(1000));
System.out.printf("%s 抱抱!\n", name);
phaser.arriveAndDeregister();
} else {
phaser.arriveAndDeregister();
}
}
@Override
public void run() {
try {
arrive();
eat();
leave();
hug();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MarriagePhaser extends Phaser {
@Override
protected boolean onAdvance(int phase, int registeredParties) {
switch (phase) {
case 0:
System.out.println("所有人到齊");
System.out.println("----------");
return false;
case 1:
System.out.println("所有人吃完");
System.out.println("----------");
return false;
case 2:
System.out.println("所有人離開");
System.out.println("----------");
return false;
case 3:
System.out.println("婚禮結束");
System.out.println("----------");
return true;
default:
return true;
}
}
}
??Phaser類似于升級版的CyclicBarrier,可用于分階段執行的事件處理,以上代碼,描述了例外婚禮的程序:所有賓客和新郎新娘到齊 > 所有人吃完飯 > 賓客離開 > 新郎新娘抱抱,婚禮結束,
ReadWriteLock
public static void testReanWriteLock() {
ReadWriteLock lock = new ReentrantReadWriteLock();
Lock readLock = lock.readLock ();
Lock writeLock = lock.writeLock();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
readLock.lock();
Sleep.sleep(2);
System.out.println(Thread.currentThread().getName() + " read...");
readLock.unlock();
}, "Thread" + i).start();
}
for (int i = 10; i < 12; i++) {
new Thread(() -> {
writeLock.lock();
Sleep.sleep(2);
System.out.println(Thread.currentThread().getName() + " write...");
writeLock.unlock();
}, "Thread" + i).start();
}
}
??ReadWriteLock提供了一個讀寫鎖(也稱為共享鎖和排他鎖)的機制,多個執行緒可以同時獲取到讀鎖(共享鎖),而同一時刻只能有一個執行緒獲取到寫鎖(排他鎖),
Semaphore
public static void testSemaphore() {
Semaphore semaphore = new Semaphore(1);
new Thread(() -> {
try {
semaphore.acquire();
System.out.println("執行緒1running");
Thread.sleep(2000);
System.out.println("執行緒1running");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}).start();
new Thread(() -> {
try {
semaphore.acquire();
System.out.println("執行緒2running");
Thread.sleep(2000);
System.out.println("執行緒2running");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}).start();
}
??Semaphore即為信號量,表示同時可以有多少個執行緒執行,其應用場景是限流,
Exchanger
public static void testExchanger() {
Exchanger<String> exchanger = new Exchanger<>();
new Thread(() -> {
String name = "Tom";
try {
name = exchanger.exchange(name);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + name);
}, "t1").start();
new Thread(() -> {
String name = "Jack";
try {
name = exchanger.exchange(name);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + name);
}, "t2").start();
}
輸出:
t2 Tom
t1 Jack
??從上面的程式可以看出,執行緒t1和t2內部的變數name發生了交換,Exchanger可用于兩個執行緒之間交換資料,也是執行緒通信的一種方式,
LockSupport
public static void testLockSupport() throws InterruptedException {
Thread t1 = new Thread(() -> {
System.out.println("t1 start and park...");
LockSupport.park();
System.out.println("t1 continue and end...");
}, "t1");
t1.start();
Thread.sleep(3000);
System.out.println("3 second later, unpark t1");
LockSupport.unpark(t1);
}
??LockSupport相比于wait()和notify()更具有靈活性,notify()是隨機喚醒一個正在等待的執行緒,而LockSupport可以喚醒一個特定的執行緒,
總結
??以上就是JUC常用類的一些基本用法,關于其內部的具體實作和原理,將在后續內容中講解,敬請期待,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/279541.html
標籤:其他
上一篇:關于凈推薦值(NPS)的理解
下一篇:MAC泛洪學習記錄
