自定义线程锁

本文介绍了如何构建一个名为`BooleanLock`的线程锁,该锁具备与`synchronized`关键字相同的功能,同时增加了可中断和超时等待的特性。通过实现`Lock`接口,`BooleanLock`在被锁定时可以记录阻塞的线程,并支持在等待锁的过程中被中断或在指定时间后超时。测试代码展示了多个线程争抢锁、中断阻塞线程以及超时释放锁的场景。
摘要由CSDN通过智能技术生成

一 点睛

构造一个线程锁 BooleanLock,使其具备 synchronized 关键字所有功能的同时又具备可中断和 lock 超时功能。

二 实战

1 接口

package concurrent.booleanLock;

import java.util.List;
import java.util.concurrent.TimeoutException;

public interface Lock {
    // 该方法用于阻塞,除非获得到了锁,这一点和 synchronized 非常类似,但是该方法是可中断的,中断时抛出 InterruptedException
    void lock() throws InterruptedException;

    // 该方法除了可以被中断以外,还增加了对应的超时功能
    void lock(long mills) throws InterruptedException, TimeoutException;

    // 进行锁的释放
    void unLock();

    // 用于获取当前有哪些线程被阻塞
    List<Thread> getBlockedThreads();
}

2 接口实现代码

package concurrent.booleanLock;

import java.util.*;
import java.util.concurrent.TimeoutException;

public class BooleanLock implements Lock {
    private Thread currentThread;

    private boolean locked = false;

    private final List<Thread> blockedList = new ArrayList<>();

    @Override
    public void lock() throws InterruptedException {
        synchronized (this) {
            while (locked) {
                final Thread tempThread = Thread.currentThread();
                try {
                    if (!blockedList.contains(tempThread)) {
                        blockedList.add(Thread.currentThread());
                    }
                    this.wait();
                } catch (InterruptedException e) {
                    blockedList.remove(tempThread);
                    throw e;
                }
            }
            blockedList.remove(Thread.currentThread());
            this.locked = true;
            this.currentThread = Thread.currentThread();
        }
    }

    @Override
    public void lock(long mills) throws InterruptedException, TimeoutException {
        synchronized (this) {
            if (mills <= 0) {
                this.lock();
            } else {
                long remainingMills = mills;
                long endMills = System.currentTimeMillis() + remainingMills;
                while (locked) {
                    if (remainingMills <= 0) {
                        throw new TimeoutException("can not get the lock during " + mills + " ms");
                    }
                    if (!blockedList.contains(Thread.currentThread())) {
                        blockedList.add(Thread.currentThread());
                    }
                    this.wait(remainingMills);
                    remainingMills = endMills - System.currentTimeMillis();
                }
                blockedList.remove(Thread.currentThread());
                this.locked = true;
                this.currentThread = Thread.currentThread();
            }
        }
    }

    @Override
    public void unLock() {
        synchronized (this) {
            if (currentThread == Thread.currentThread()) {
                this.locked = false;
                Optional.of(Thread.currentThread().getName() + " release ths lock.").ifPresent(System.out::println);
                this.notifyAll();
            }
        }
    }

    @Override
    public List<Thread> getBlockedThreads() {
        return Collections.unmodifiableList(blockedList);
    }
}

3 测试代码

package concurrent.booleanLock;


import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;


public class BooleanLockTest {
    private final Lock lock = new BooleanLock();


    public void syncMethod() {
        try {
            lock.lock();
            int randomInt = new Random().nextInt(10);
            System.out.println(Thread.currentThread() + " get the Lock.");
            TimeUnit.SECONDS.sleep(randomInt);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unLock();
        }
    }


    public void syncMethodTimeout() {
        try {
            lock.lock(1000);
            int randomInt = new Random().nextInt(10);
            System.out.println(Thread.currentThread() + " get the Lock.");
            TimeUnit.SECONDS.sleep(randomInt);
        } catch (InterruptedException | TimeoutException e) {
            e.printStackTrace();
        } finally {
            lock.unLock();
        }
    }


    public static void main(String[] args) {
        // 1 多个线程通过 lock() 方法争抢锁
//        BooleanLockTest test = new BooleanLockTest();
//        IntStream.range(0, 10).mapToObj(i -> new Thread(test::syncMethod)).forEach(Thread::start);
        // 2 可中断被阻塞的线程
//        BooleanLockTest test1 = new BooleanLockTest();
//        new Thread(test1::syncMethod, "T1").start();
//        try {
//            TimeUnit.MILLISECONDS.sleep(2);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        Thread t2 = new Thread(test1::syncMethod, "T2");
//        t2.start();
//        try {
//            TimeUnit.MILLISECONDS.sleep(10);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        t2.interrupt();
        // 3 阻塞的线程可超时
        BooleanLockTest test2 = new BooleanLockTest();
        new Thread(test2::syncMethod, "T1").start();
        try {
            TimeUnit.MILLISECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Thread t2 = new Thread(test2::syncMethodTimeout, "T2");
        t2.start();
        try {
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

三 测试结果

1 多个线程通过 lock() 方法争抢锁

Thread[Thread-0,5,main] get the Lock.

Thread-0 release ths lock.

Thread[Thread-7,5,main] get the Lock.

Thread-7 release ths lock.

Thread[Thread-1,5,main] get the Lock.

Thread-1 release ths lock.

Thread[Thread-6,5,main] get the Lock.

Thread-6 release ths lock.

Thread[Thread-2,5,main] get the Lock.

Thread-2 release ths lock.

Thread[Thread-9,5,main] get the Lock.

Thread-9 release ths lock.

Thread[Thread-4,5,main] get the Lock.

Thread-4 release ths lock.

Thread[Thread-8,5,main] get the Lock.

Thread-8 release ths lock.

Thread[Thread-5,5,main] get the Lock.

Thread-5 release ths lock.

Thread[Thread-3,5,main] get the Lock.

Thread-3 release ths lock.

2 可中断被阻塞的线程

Thread[T1,5,main] get the Lock.

java.lang.InterruptedException

    at java.lang.Object.wait(Native Method)

    at java.lang.Object.wait(Object.java:502)

    at concurrent.booleanLock.BooleanLock.lock(BooleanLock.java:22)

    at concurrent.booleanLock.BooleanLockTest.syncMethod(BooleanLockTest.java:12)

    at java.lang.Thread.run(Thread.java:748)

3 阻塞的线程可超时

Thread[T1,5,main] get the Lock.

java.util.concurrent.TimeoutException: can not get the lock during 1000 ms

    at concurrent.booleanLock.BooleanLock.lock(BooleanLock.java:44)

    at concurrent.booleanLock.BooleanLockTest.syncMethodTimeout(BooleanLockTest.java:25)

    at java.lang.Thread.run(Thread.java:748)

T1 release ths lock.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值