使用synchronized写一个显示锁
public interface MyLock { void lock () throws InterruptedException; void lock(long millis) throws TimeoutException , InterruptedException ,ParametersIllegalException; void unlock(); class TimeoutException extends Exception{ TimeoutException(String msg){ super(msg); } private static final long serialVersionUID = 1L; } class ParametersIllegalException extends Exception{ ParametersIllegalException(String msg){ super(msg); } private static final long serialVersionUID = 1L; } }
public class MyLockImpl implements MyLock{ private boolean initValue; // false表示monitor没有被占用 private Thread currentThread; @Override public synchronized void lock() throws InterruptedException { while(initValue) {//monitor被占用 this.wait(); } initValue = true; currentThread = Thread.currentThread(); } @Override public synchronized void unlock() { if(currentThread == Thread.currentThread()) { System.out.println("【"+Thread.currentThread().getName()+"】" + " release the monitor"); initValue = false; this.notifyAll(); } } @Override public synchronized void lock(long millis) throws TimeoutException, InterruptedException, ParametersIllegalException { if (millis <= 0) throw new ParametersIllegalException("parameters illegal"); long hasRemaining = millis; long endTime = System.currentTimeMillis() + millis; while (initValue) { if (hasRemaining <= 0) throw new TimeoutException("Time out"); this.wait(millis); hasRemaining = endTime - System.currentTimeMillis(); } this.initValue = true; this.currentThread = Thread.currentThread(); } }
public class MyLockTest { public static void main(String[] args) { MyLock myLock = new MyLockImpl(); Stream.of("T1","T2","T3","T4").forEach(name -> new Thread(()-> { try { myLock.lock(10); System.out.println("【"+Thread.currentThread().getName()+"】" +" get the monitor"); m1(); } catch (InterruptedException e) { e.printStackTrace(); } catch (TimeoutException e) { System.out.println("【"+Thread.currentThread().getName()+"】" +" timeout"); } catch (ParametersIllegalException e) { System.out.println("【"+Thread.currentThread().getName()+"】" +" parameter illegal"); //e.printStackTrace(); }finally { myLock.unlock(); } },name).start() ); } public static void m1() throws InterruptedException { System.out.println("【"+Thread.currentThread().getName()+"】" + "is working ..."); Thread.sleep(3_000); } }
注意wait方法可能存在spurious(假的)唤醒,wait方法应该在一个循环中使用