Java 实现一个自己的显式锁Lock(有超时功能)

Lock接口

package concurency.chapter9;


import java.util.Collection;

public interface Lock {
    static class TimeOutException extends Exception {
        TimeOutException(String message) {
            super(message);
        }
    }

    void lock() throws InterruptedException;

    void lock(long mills) throws InterruptedException,TimeOutException;

    void unlock();

    Collection<Thread> getBlockedThread();

    int getBlockedSize();
}

Lock实现类

package concurency.chapter9;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;

public class BooleanLock implements Lock{
    public BooleanLock(boolean initValue) {
        this.initValue = initValue;
    }

    // false means is free
    // true means having been used
    private boolean initValue;

    private Thread currentThread;

    private Collection<Thread> blockedThreads = new ArrayList<>();

    @Override
    public synchronized void lock() throws InterruptedException {
        while(initValue) {
            blockedThreads.add(Thread.currentThread());
            this.wait();
        }

        blockedThreads.remove(Thread.currentThread());
        this.initValue = true;
        this.currentThread = Thread.currentThread();
    }

    @Override
    public synchronized void lock(long mills) throws InterruptedException, TimeOutException {
        // less than 0, Ignore it..
        if(mills <= 0)
            lock();
        long hasRemaining = mills;
        long endTime = System.currentTimeMillis() + mills;
        while(initValue) {
            if(hasRemaining <= 0)
                throw new TimeOutException("time out, and the Thread[" + Thread.currentThread().getName()+"] do not get the lock");
            blockedThreads.add(Thread.currentThread());
            this.wait(mills);
            hasRemaining = endTime - System.currentTimeMillis();
        }
        blockedThreads.remove(Thread.currentThread());
        this.initValue = true;
        this.currentThread = Thread.currentThread();
    }

    @Override
    public synchronized void unlock() {
        if(currentThread != null && Thread.currentThread() == currentThread) {
            this.initValue = false;
            Optional.of(Thread.currentThread().getName() + " release the lock...").ifPresent(System.out::println);
            this.notifyAll();
        }
    }

    @Override
    public Collection<Thread> getBlockedThread() {
        return Collections.unmodifiableCollection(blockedThreads);
    }

    @Override
    public int getBlockedSize() {
        return blockedThreads.size();
    }
}

测试

package concurency.chapter9;

import java.util.Optional;
import java.util.stream.Stream;

public class LockTest {
    public static void main(String[] args) throws InterruptedException {

        final BooleanLock booleanLock = new BooleanLock(false);
        Stream.of("T1", "T2", "T3", "T4")
                .forEach(name ->
                        new Thread(() -> {
                            try {
                                booleanLock.lock(1000L);
                                Optional.of(Thread.currentThread().getName() + " have the lock Monitor")
                                        .ifPresent(System.out::println);
                                work();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            } catch (Lock.TimeOutException e) {
                                System.out.println(e.getMessage());
//                                Optional.of(Thread.currentThread().getName() + " time out")
//                                        .ifPresent(System.out::println);
                            } finally {
                                booleanLock.unlock();
                            }
                        }, name).start()
                );
    }

    private static void work() throws InterruptedException {
        Optional.of(Thread.currentThread().getName() + " is Working...")
                .ifPresent(System.out::println);
        Thread.sleep(10_000);
    }
}

测试结果

T1 have the lock Monitor
T1 is Working...
time out, and the Thread[T2] do not get the lock
time out, and the Thread[T3] do not get the lock
time out, and the Thread[T4] do not get the lock
T1 release the lock...
posted @ 2019-02-15 00:25  Draymonder  阅读(1438)  评论(0编辑  收藏  举报