一、概述
- 当有10个线程在调用一个被synchronized的方法时,只有当前拿到锁的线程执行完之后,其它9个线程才能有一个线程抢到锁。反复如此,如果方法固定调用时长为10秒,执行完成之后就是100秒。
- 所以当我们调用这个方法的时候想要设置一个超时时间,超过之间就放弃调用。
二、代码
public class Thread13 {
public static void main(String[] args) {
final BooleanLock booleanLock = new BooleanLock();
Thread thread1 = new Thread(new Runnable() {
public void run() {
try {
booleanLock.lock();
working();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
booleanLock.unlock();
}
}
},"t1");
thread1.start();
Thread thread2 = new Thread(new Runnable() {
public void run() {
try {
booleanLock.lock();
working();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
booleanLock.unlock();
}
}
},"t2");
thread2.start();
Thread thread3 = new Thread(new Runnable() {
public void run() {
try {
booleanLock.lock();
working();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
booleanLock.unlock();
}
}
},"t3");
thread3.start();
Thread thread4 = new Thread(new Runnable() {
public void run() {
try {
booleanLock.lock(5*1000);
working();
} catch (InterruptedException e) {
e.printStackTrace();
} catch(TimeOutException e) {
System.out.println(Thread.currentThread().getName() + " timeOut");
} finally {
booleanLock.unlock();
}
}
},"t4");
thread4.start();
}
public static void working() {
try {
System.out.println(Thread.currentThread().getName() + " working...");
Thread.sleep(10*1000);
System.out.println(Thread.currentThread().getName() + " working end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 锁接口
* @author chenfenli
*
*/
public static interface Lock {
class TimeOutException extends Exception {
private static final long serialVersionUID = 1L;
public TimeOutException(String message) {
super(message);
}
}
/**
* 加锁
* @throws InterruptedException
*/
public void lock() throws InterruptedException;
/**
* 加锁
* @param timeOut 超时时间 毫秒
* @throws InterruptedException
*/
public void lock(long timeOut) throws InterruptedException,TimeOutException;
/**
* 释放锁
*/
public void unlock();
/*
* 获取处于wait状态中的锁
*/
public Collection<Thread> getBlockedThread();
/**
* 获取处于wait状态中的锁的数量
* @return
*/
public Integer getBlockedSize();
}
public static class BooleanLock implements Lock {
public boolean flag = false;
// 等待线程集合
public Collection<Thread> blockedTheadList = new ArrayList<Thread>();
public Thread thisThread = null;
public synchronized void lock() throws InterruptedException {
while (flag) {
// 锁已被其它线程所用 -> 将对象设置为wait,释放锁,并加入到集合
if(!blockedTheadList.contains(Thread.currentThread())) {
blockedTheadList.add(Thread.currentThread());
}
System.out.println(Thread.currentThread().getName() + " wait 等待线程数:" + blockedTheadList.size());
this.wait();
}
System.out.println(Thread.currentThread().getName() + " start 等待线程数:" + blockedTheadList.size());
flag = true;
thisThread = Thread.currentThread();
}
public synchronized void lock(long timeOut) throws InterruptedException, TimeOutException {
if(timeOut <= 0) {
lock();
return;
}
long endTime = System.currentTimeMillis() + timeOut;
while (flag) {
if(!blockedTheadList.contains(Thread.currentThread())) {
blockedTheadList.add(Thread.currentThread());
}
System.out.println(Thread.currentThread().getName() + " timewait 等待线程数:" + blockedTheadList.size());
if(System.currentTimeMillis() - endTime > 0) {
blockedTheadList.remove(Thread.currentThread());
throw new TimeOutException("timeOut");
}
this.wait(timeOut);
}
System.out.println(Thread.currentThread().getName() + " start 等待线程数:" + blockedTheadList.size());
flag = true;
thisThread = Thread.currentThread();
}
public synchronized void unlock() {
if(thisThread == Thread.currentThread()) {
blockedTheadList.remove(Thread.currentThread());
flag = false;
System.out.println(Thread.currentThread().getName() + " unlock 等待线程数:" + blockedTheadList.size());
this.notifyAll();
}
}
public Collection<Thread> getBlockedThread() {
return Collections.unmodifiableCollection(blockedTheadList);
}
public Integer getBlockedSize() {
return blockedTheadList.size();
}
}
t1 start 等待线程数:0
t1 working...
t2 wait 等待线程数:1
t3 wait 等待线程数:2
t4 timewait 等待线程数:3
t4 timewait 等待线程数:3
t4 timeOut
t1 working end
t1 unlock 等待线程数:2
t3 start 等待线程数:2
t3 working...
t2 wait 等待线程数:2
t3 working end
t3 unlock 等待线程数:1
t2 start 等待线程数:1
t2 working...
t2 working end
t2 unlock 等待线程数:0