写于:2020-02-26
synchronized 本身的功能比较单一。在此基础上实现一个具有可中断和超时功能的显示锁。
一、代码设计
1.1、接口设计
代码如下
/**
* <p> 自定义锁 接口规范 </p>
*/
public interface Lock {
/** 自定义超时异常 **/
class TimeOutException extends Exception{
public TimeOutException(String messag){
super(messag);
}
}
/** 加锁 **/
void lock() throws InterruptedException;
/** 带有超时时间的加锁 **/
void lock(long mills) throws InterruptedException,TimeOutException;
/** 释放锁 **/
void unlock();
/** 获取被 BLock 的线程 **/
Collection<Thread> getBlockedThread();
/** 获取被 Block 的线程数量 **/
int getBlockedSize();
}
定义了如下几个方法接口
- 1、没有超时间的加锁方法 lock()
- 2、带有超时时间的的加锁方法 lock(long)
- 3、释放锁的方法 unlock()
- 4、获取当前正在等待锁的线程集合
- 5、获取当前正在等待锁的线程数
1.2、代码实现
总体代码如下
public class BooleanLock implements Lock {
/**
* true 表示,该锁被占用
* false 表示,该锁空闲
*/
private boolean initValule;
/** 被阻塞的线程集合 **/
private Collection<Thread> blockedThreadCollection = new ArrayList<>();
/** 占用当前锁的线程 **/
private Thread currentThread;
public BooleanLock() {
this.initValule = false;
}
@Override
public synchronized void lock() throws InterruptedException {
// 锁被占用
while (initValule){
blockedThreadCollection.add(Thread.currentThread());
this.wait();
}
// 锁未被占用
blockedThreadCollection.remove(Thread.currentThread());
this.initValule = true;
this.currentThread = Thread.currentThread();
}
@Override
public synchronized void lock(long mills) throws InterruptedException, TimeOutException {
if(mills <= 0)
lock();
long hashRemaing = mills; // 超时时间
long endTime = System.currentTimeMillis() + mills; // 时间在此之后判定为超时
while (initValule){
if(hashRemaing <= 0)
throw new TimeOutException("Time out");
blockedThreadCollection.add(Thread.currentThread());
this.wait(mills);
hashRemaing = endTime - System.currentTimeMillis();
}
blockedThreadCollection.remove(Thread.currentThread());
this.initValule = true;
this.currentThread = Thread.currentThread();
}
@Override
public synchronized void unlock() {
if(this.currentThread.equals(Thread.currentThread())){
initValule = false;
System.out.println(Thread.currentThread().getName() + ",release the lock monitor");
this.notifyAll();
}
}
@Override
public Collection<Thread> getBlockedThread() {
return Collections.unmodifiableCollection(this.blockedThreadCollection);
}
@Override
public int getBlockedSize() {
return blockedThreadCollection.size();
}
}
1.3、代码测试
public class LockTest {
public static void main(String[] args) throws InterruptedException {
BooleanLock lock = new BooleanLock();
Stream.of("T1","T2","T3","T4").forEach(item ->{
new Thread(){
@Override
public void run() {
try {
lock.lock(10L); // 超时时间的锁
work();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Lock.TimeOutException e) {
System.out.println(Thread.currentThread().getName() + ",Time out");
} finally {
lock.unlock();
}
}
}.start();
});
Thread.sleep(10_000);
lock.unlock();
}
public static void work() throws InterruptedException {
System.out.println(Thread.currentThread().getName() + ",is working");
Thread.sleep(1_000);
}
}