# 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