Lock接口
1. 介绍
与synchronized相比,Lock显示锁的定义,结构更加灵活。
提供更多的实用性方法,功能更强大,性能更好一些。
常用方法
void lock() //获取锁,如果锁被占用,就等待
boolean tryLock() //尝试获取锁,成功就返回true
void unlock() //释放锁
2. Lock接口的实现类一般是ReentrantLock
(常用)
案例,四个窗口共卖一百张票。
步骤
1. 创建卖一百张票的任务
2. 用四个线程去执行
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
public static void main(String[] args) {
//创建任务
Runnable sellTicket = new Runnable() {
//定义锁
private Lock lock = new ReentrantLock();
//定义票
private int ticket = 100;
@Override
public void run() {
while (true) {
lock.lock();
try {
if (ticket <= 0) {
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在售卖第" + ticket + "张票");
this.ticket--;
} finally {
lock.unlock();
}
}
}
};
ExecutorService es = Executors.newFixedThreadPool(4);
for (int i = 0; i < 4; i++){
es.submit(sellTicket);
}
es.shutdown();
while (es.isTerminated()){}
}
}
结果:
3. 补充ReadWriteLock接口
其实例类如下所示ReentrantReadWriteLock
(用于读写环境的情况下,效率更高)
ReentrantReadWriteLock是一种支持一写多读的同步锁,读写分离,可分别分配读锁和写锁。
支持多次分配读锁,使多个读操作可以并发执行。
写--写:互斥,阻塞
读--写:互斥,读阻塞写、写阻塞读
读--读:不互斥,不阻塞
有点: 在读操作远远多于,写操作的时候,可以提高效率。
案例 一个变量value
需要被18个线程进行读操作,2个线程进行写操作。
思路:
1. 创建一个读写类ReadWrite,里面还有一个变量value,一个锁lock。
2. 实现value的get以及set方法,方法内部在针对变量value的修改或者读取的时候,需要加上锁。
3. 在主函数里,创建两个任务,分别用来调用ReadWrite里面实现的读写方法。
4. 创建线程池,容量为20,将读写任务分别提交。
代码
/*
** ReadWrite类
*/
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 ReadWrite {
private ReadWriteLock lock = new ReentrantReadWriteLock();
private int value;
public int getValue() {
lock.readLock().lock();
try {
//延缓输出
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return value;
}
finally {
lock.readLock().unlock();
}
}
public void setValue(int value) {
lock.writeLock().lock();
try {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.value = value;
}
finally {
lock.writeLock().unlock();
}
}
}
主函数
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestReentrantReadWriteLock {
public static void main(String[] args) {
//实例化对象
ReadWrite readWrite = new ReadWrite();
//创建线程池
ExecutorService es = Executors.newFixedThreadPool(20);
//写需要完成的任务
Runnable write = new Runnable() {
@Override
public void run() {
int n = new Random().nextInt(100);
readWrite.setValue(n);
System.out.println(Thread.currentThread().getName() + "正在写入----" + n);
}
};
Runnable read = new Runnable() {
@Override
public void run() {
int n = readWrite.getValue();
System.out.println(Thread.currentThread().getName() + "正在读出----" + n);
}
};
long start = System.currentTimeMillis();
//将任务放到线程池里面
for(int i = 0;i < 15; i++){
es.submit(write);
}
for (int i = 0; i < 5; i++){
es.submit(read);
}
es.shutdown();
while (!es.isTerminated()){}
long end = System.currentTimeMillis();
System.out.println("耗费时间为--" + (end - start));
}
}