自定义Lock显示锁
public interface Lock {
class TimeOutException extends Exception {
public TimeOutException(String message) {
super(message);
}
}
/**
* 加锁
*
* @throws InterruptedException 打断异常
*/
void lock() throws InterruptedException;
/**
* 加锁
*
* @param mills 加锁时间
* @throws InterruptedException 打断异常
* @throws TimeOutException 超时异常
*/
void lock(long mills) throws InterruptedException, TimeOutException;
/**
* 解锁
*/
void unlock();
/**
* 获取争抢锁时被阻塞的线程
*
* @return 被阻塞线程的集合
*/
Collection<Thread> getBlockedThread();
/**
* 获取争抢锁时被阻塞的线程的数量
*
* @return 被阻塞的线程的数量
*/
int getBlockedSize();
}
public class BooleanLock implements Lock {
/**
* The initValue is true indicated the lock has been get.
* The initValue is false indicated the lock is free (other thread can get this).
*/
private boolean initValue;
private Collection<Thread> blockedThreadCollection = new ArrayList<>();
private Thread currentThread;
public BooleanLock() {
this.initValue = false;
}
@Override
public synchronized void lock() throws InterruptedException {
// 锁已经被其他线程使用
while (initValue) {
blockedThreadCollection.add(Thread.currentThread());
this.wait();
}
// 锁未被使用,抢到锁立即设置initValue的值
this.initValue = true;
this.currentThread = Thread.currentThread();
blockedThreadCollection.remove(Thread.currentThread());
}
@Override
public synchronized void lock(long mills) throws InterruptedException, TimeOutException {
if (mills <= 0) {
lock();
}
long hasRemaining = mills;
long endTime = System.currentTimeMillis() + mills;
while (initValue) {
if (hasRemaining <= 0) {
throw new TimeOutException("Time Out");
}
blockedThreadCollection.add(Thread.currentThread());
this.wait(mills);
hasRemaining = endTime - System.currentTimeMillis();
// System.out.println(Thread.currentThread().getName() + ">>" + hasRemaining);
}
this.initValue = true;
this.currentThread = Thread.currentThread();
}
@Override
public synchronized void unlock() {
// 释放锁
if (Thread.currentThread() == currentThread) {
this.initValue = false;
Optional.of(Thread.currentThread().getName() + " release the lock monitor.").ifPresent(System.out::println);
this.notifyAll();
}
}
@Override
public Collection<Thread> getBlockedThread() {
// 可以直接返回,但是不安全。此处返回的是一个实例,调用者可以随意更改(null,clear()等操作)。
return Collections.unmodifiableCollection(blockedThreadCollection);
}
@Override
public int getBlockedSize() {
return blockedThreadCollection.size();
}
}
public class LockTest {
public static void main(String[] args) throws InterruptedException {
final BooleanLock booleanLock = new BooleanLock();
Stream.of("T1", "T2", "T3", "T4").forEach(name -> {
new Thread(() -> {
try {
booleanLock.lock(5000L);
Optional.of(Thread.currentThread().getName() + " have the lock Monitor.").ifPresent(System.out::println);
work();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Lock.TimeOutException e) {
Optional.of(Thread.currentThread().getName() + " time out.").ifPresent(System.out::println);
} finally {
booleanLock.unlock();
}
}, name).start();
});
// 问题:违规非法操作。导致运行混乱
/*Thread.sleep(100);
booleanLock.unlock();*/
}
private static void work() throws InterruptedException {
Optional.of(Thread.currentThread().getName() + " is working...").ifPresent(System.out::println);
Thread.sleep(10_000);
}
}