# lock接口
為鎖和等待條件提供一個框架的接口和類,它不同于內置的synchronized同步和monitor監視器。
Lock不是Java語言內置的,是在java.util工具包里面的。需要開發人員手動加鎖和解鎖。
## ReentrantLock
可重入鎖:同一個線程的不同被鎖住的方法可以直接進入。synchronized也是可重入鎖,ReentrantLock可以用來替代synchronized,但是需要手動解鎖。
~~~
?ReentrantLock lock = new ReentrantLock();
??
?public void method() {
? ? ?// 上鎖
? lock.lock();
? ? ?/*--------------------
? ? ?* 業務操作
? ? ?*/
? ? ?// 解鎖
? ? ?// 一定要寫在finally代碼塊中保證會被釋放掉
? ? ?lock.unlock();
?}
~~~
1. tryLock(),在n秒時間內嘗試獲取鎖對象,不管獲取與否方法都會繼續執行,但是可以根據該方法的返回值來判斷是否獲取到鎖了。
2. lock.lockInterruptibly(),可以被thread.interrupt()打斷。
3. new ReetrantLock(true),公平鎖。線程會在等待隊列中排隊等待。如果是非公平的線程會直接搶占鎖。多個線程之間會交替執行,而不會讓一個線程獨占鎖。
## CounDownLatch
當主線程需要在子線程的工作完成后才能繼續運行時可以使用這個類進行阻塞。
~~~
?CountDownLatch countDownLatch = new CountDownLathc(2); // 建立2個線程空間
?new Thread(() -> {
? // 處理
? countDownLatch.countDown(); // 值減一
?});
?countDownLatch.await(); // 阻塞主線程
~~~
當countDown的值減為0的時候主線程可以繼續往下運行,否則的話阻塞,等待子線程運行完成。
比thread.join()靈活。
### CyclicBarrier
當線程數達到設定的值的時候就會運行設定的代碼。
~~~
?package net.smrobot._thread.day04;
?import java.util.concurrent.BrokenBarrierException;
?import java.util.concurrent.CyclicBarrier;
?public class T07_CyclicBarrierTest {
? ? ?public static void main(String[] args) {
? ? ? ? ?// 滿20人之后調用第二個參數指定的動作
? ? ? ? ?CyclicBarrier barrier = new CyclicBarrier(20, new Runnable() {
? ? ? ? ? ? ?@Override
? ? ? ? ? ? ?public void run() {
? ? ? ? ? ? ? ? ?System.out.println("barrier start");
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? ?for (int i = 0; i < 100; i++) {
? ? ? ? ? ? ?new Thread(() -> {
? ? ? ? ? ? ? ? ?try {
? ? ? ? ? ? ? ? ? ? ?// 等待,每20個線程才會被放行
? ? ? ? ? ? ? ? ? ? ?barrier.await();
? ? ? ? ? ? ? ? ? ? ?System.out.println("11");
? ? ? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? ? ?e.printStackTrace();
? ? ? ? ? ? ? ? } catch (BrokenBarrierException e) {
? ? ? ? ? ? ? ? ? ? ?e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }).start();
? ? ? ? }
? ? }
?}
??
~~~
可以用在流量限流或者是有個線程要等其他線程結束了才能運行。
> 備注:限流類:Guava RateLimiter
### Phaser
分解段運行,在遺傳算法中可以用上。
每個階段都會設置棧欄。
### ReadWriteLock
讀寫鎖,當有讀線程在讀的時候其他線程也可以讀數據,寫線程等待,而寫線程是互斥的。
~~~
?package net.smrobot._thread.day04;
??
??
?import java.util.Random;
?import java.util.concurrent.locks.Lock;
?import java.util.concurrent.locks.ReadWriteLock;
?import java.util.concurrent.locks.ReentrantLock;
?import java.util.concurrent.locks.ReentrantReadWriteLock;
??
?public class T09_ReadWriteLockTest {
? ? ?static Lock lock = new ReentrantLock();
? ? ?private static int value;
??
? ? ?static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
? ? ?static Lock readLock = readWriteLock.readLock();
? ? ?static Lock writeLock = readWriteLock.writeLock();
??
? ? ?public static void main(String[] args) {
? ? ? ? ?// 使用互斥鎖
?// ? ? ? Runnable readR = () -> read(lock);
?// ? ? ? Runnable writeR = () -> write(lock, new Random().nextInt());
? ? ? ? ?// 使用讀寫鎖
? ? ? ? ?Runnable readR = () -> read(readLock);
? ? ? ? ?Runnable writeR = () -> write(writeLock, new Random().nextInt());
??
? ? ? ? ?for (int i = 0; i < 10; i++) {
? ? ? ? ? ? ?new Thread(readR).start();
? ? ? ? }
? ? ? ? ?for (int i = 0; i < 2; i++) {
? ? ? ? ? ? ?new Thread(writeR).start();
? ? ? ? }
??
??
? ? }
??
? ? ?public static void read(Lock lock) {
? ? ? ? ?try {
? ? ? ? ? ? ?lock.lock();
? ? ? ? ? ? ?Thread.sleep(1000);
? ? ? ? ? ? ?System.out.println("read over!");
? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ?e.printStackTrace();
? ? ? ? } finally {
? ? ? ? ? ? ?lock.unlock();
? ? ? ? }
??
? ? }
??
? ? ?public static void write(Lock lock, int value) {
? ? ? ? ?try {
? ? ? ? ? ? ?lock.lock();
? ? ? ? ? ? ?Thread.sleep(1000);
? ? ? ? ? ? ?value = value;
? ? ? ? ? ? ?System.out.println("write over!");
? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ?e.printStackTrace();
? ? ? ? } finally {
? ? ? ? ? ? ?lock.unlock();
? ? ? ? }
? ? }
?}
??
~~~
`StampedLock`
### semaphore
信號量,可以用來限流,可以同時設置多少個線程運行。
~~~
?package net.smrobot._thread.day04;
??
?import java.util.concurrent.Semaphore;
??
?public class T10_SemaphoreTest {
??
? ? ?public static void main(String[] args) {
? ? ? ? ?Semaphore s = new Semaphore(2);
? ? ? ? ?// 公平鎖
? ? ?//Semaphore s = new Semaphore(2, true);
? ? ? ? ?new Thread(() -> {
? ? ? ? ? ? ?try {
? ? ? ? ? ? ? ? ?// 信號量中獲取鎖
? ? ? ? ? ? ? ? ?s.acquire();
? ? ? ? ? ? ? ? ?System.out.println("t1 running ...");
? ? ? ? ? ? ? ? ?Thread.sleep(1000);
? ? ? ? ? ? ? ? ?System.out.println("t1 running ....");
? ? ? ? ? ? ? ? ?// 釋放鎖
? ? ? ? ? ? ? ? ?s.release();
? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ?e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }).start();
??
? ? ? ? ?new Thread(() -> {
? ? ? ? ? ? ?try {
? ? ? ? ? ? ? ? ?s.acquire();
? ? ? ? ? ? ? ? ?System.out.println("t2 running ...");
? ? ? ? ? ? ? ? ?Thread.sleep(1000);
? ? ? ? ? ? ? ? ?System.out.println("t2 running ....");
? ? ? ? ? ? ? ? ?s.release();
? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ?e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }).start();
??
? ? }
?}
??
~~~
### Exchanger
用于線程之間通信交換數據,只能用于兩個線程之間交換數據,兩個線程同時使用exchanger。
~~~
?package net.smrobot._thread.day04;
??
?import java.util.concurrent.Exchanger;
??
?public class T11_ExchangerTest {
? ? ?static Exchanger<String> exchanger = new Exchanger<>();
? ? ?public static void main(String[] args) {
??
? ? ? ? ?new Thread(() -> {
? ? ? ? ? ? ?String s1 = "t1";
? ? ? ? ? ? ?try {
? ? ? ? ? ? ? ? ?s1 = exchanger.exchange(s1);
? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ?e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? ? ? ?System.out.println(Thread.currentThread().getName() + s1);
? ? ? ? }, "T1").start();
??
? ? ? ? ?new Thread(() -> {
? ? ? ? ? ? ?String s2 = "t2";
? ? ? ? ? ? ?try {
? ? ? ? ? ? ? ? ?s2 = exchanger.exchange(s2);
? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? ?e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? ? ? ?System.out.println(Thread.currentThread().getName() + s2);
? ? ? ? }, "T2").start();
??
? ? }
?}
??
~~~
### LockSupport
直接使用里面的靜態方法,可以暫停某個線程運行與重啟。
~~~
?// 暫停線程的運行
?LockSupport.park();
??
?// 喚醒線程
?LockSupport.unpark(thread);
~~~
可以先調用unpark(t),此時park()不起作用。
- 第一章 Java基礎
- ThreadLocal
- Java異常體系
- Java集合框架
- List接口及其實現類
- Queue接口及其實現類
- Set接口及其實現類
- Map接口及其實現類
- JDK1.8新特性
- Lambda表達式
- 常用函數式接口
- stream流
- 面試
- 第二章 Java虛擬機
- 第一節、運行時數據區
- 第二節、垃圾回收
- 第三節、類加載機制
- 第四節、類文件與字節碼指令
- 第五節、語法糖
- 第六節、運行期優化
- 面試常見問題
- 第三章 并發編程
- 第一節、Java中的線程
- 第二節、Java中的鎖
- 第三節、線程池
- 第四節、并發工具類
- AQS
- 第四章 網絡編程
- WebSocket協議
- Netty
- Netty入門
- Netty-自定義協議
- 面試題
- IO
- 網絡IO模型
- 第五章 操作系統
- IO
- 文件系統的相關概念
- Java幾種文件讀寫方式性能對比
- Socket
- 內存管理
- 進程、線程、協程
- IO模型的演化過程
- 第六章 計算機網絡
- 第七章 消息隊列
- RabbitMQ
- 第八章 開發框架
- Spring
- Spring事務
- Spring MVC
- Spring Boot
- Mybatis
- Mybatis-Plus
- Shiro
- 第九章 數據庫
- Mysql
- Mysql中的索引
- Mysql中的鎖
- 面試常見問題
- Mysql中的日志
- InnoDB存儲引擎
- 事務
- Redis
- redis的數據類型
- redis數據結構
- Redis主從復制
- 哨兵模式
- 面試題
- Spring Boot整合Lettuce+Redisson實現布隆過濾器
- 集群
- Redis網絡IO模型
- 第十章 設計模式
- 設計模式-七大原則
- 設計模式-單例模式
- 設計模式-備忘錄模式
- 設計模式-原型模式
- 設計模式-責任鏈模式
- 設計模式-過濾模式
- 設計模式-觀察者模式
- 設計模式-工廠方法模式
- 設計模式-抽象工廠模式
- 設計模式-代理模式
- 第十一章 后端開發常用工具、庫
- Docker
- Docker安裝Mysql
- 第十二章 中間件
- ZooKeeper