JAVA多线程——自定义显示锁BooleanLock


prtyaa
prtyaa 2023-12-30 21:24:11 52202 赞同 0 反对 0
分类: 资源
synchronized是java多线程里面一个比较很重要的关键字,它提供了一种排他式的同步机制,在某个时间内,如果其中一个线程获取了锁,那么其他线程试图获取锁,就会进入阻塞状态,等到某个线程释放了锁才能获取锁。

而这种阻塞有两个比较明显的缺点:

  1. 无法控制阻塞时长
  2. 阻塞不可中断

利用java多线程的知识,可以自己动手构造一个BooleanLock,使其在具有synchronized功能的基础之上又具备可中断和超时的功能。

Lock接口

package Lock.BooleanLock;

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

public interface Lock {
    //上锁
    void lock() throws InterruptedException;
    //带超时功能的锁
    void lock(long mills) throws InterruptedException, TimeoutException;
    //解锁
    void unLock();
    //获取当前哪些进程被阻塞
    List<Thread> getBlockedThreads();
}

BooleanLock实现

package Lock.BooleanLock;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeoutException;

import static java.lang.System.currentTimeMillis;
import static java.lang.Thread.currentThread;

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){
            //获取当前线程
            final Thread tempThread = currentThread();
            //线程是否进入了阻塞状态,如果进入了加入阻塞队列
            while (locked){
                try {
                    if (!blockedList.contains(tempThread)){
                        blockedList.add(tempThread);
                    }
                    this.wait();
                }catch (InterruptedException e){
                    //被中断后移除阻塞队列
                    blockedList.remove(currentThread());
                    throw e;
                }

            }
            //如果当前线程没有获取锁,则拿到锁,移除阻塞队列
            blockedList.remove(currentThread());
            this.locked = true;
            this.currentThread = currentThread();
        }
    }

    @Override
    public void lock(long mills) throws InterruptedException, TimeoutException {
        synchronized (this){
            //判断设置超时时间是否<=0
            if (mills<=0){
                this.lock();
            }else {
                long remainingMills = mills;
                long endMills = currentTimeMillis() +remainingMills;
                //该方法同上面一样,加入了计时功能
                while (locked){
                    if (remainingMills<=0){
                        throw new TimeoutException("不能获得锁");
                    }
                    if (!blockedList.contains(currentThread())){
                        blockedList.add(currentThread());
                        this.wait(remainingMills);
                        remainingMills = endMills - currentTimeMillis();
                    }
                }
                blockedList.remove(currentThread());
                this.locked = true;
                this.currentThread = currentThread();
            }
        }
    }

    @Override
    public void unLock() {
        synchronized (this){
            if (currentThread == currentThread()){
                this.locked = false;
                Optional.of(currentThread().getName()+"释放了锁")
                        .ifPresent(System.out::println);
                this.notifyAll();
            }
        }
    }

    @Override
    public List<Thread> getBlockedThreads() {
        //返回不可变的list
        return Collections.unmodifiableList(blockedList);
    }
}

 

package Lock.BooleanLock;
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(1000);
            System.out.println(Thread.currentThread()+"得到了锁");
            TimeUnit.SECONDS.sleep(1);
        }catch (InterruptedException | TimeoutException e){
            e.printStackTrace();
        } finally {
            lock.unLock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        BooleanLockTest booleanLockTest = new BooleanLockTest();
//        IntStream.range(0,10).mapToObj(i-> new Thread(booleanLockTest::syncMethod,"T1"))
//                .forEach(Thread::start);
        new Thread(booleanLockTest::syncMethod,"t1").start();
        Thread t2 = new Thread(booleanLockTest::syncMethod,"T2");
        t2.start();
        TimeUnit.MILLISECONDS.sleep(10);

    }
}

测试超时任务,超时时间小于线程sleep时间,会抛出异常,具体测试可以自己进行。

如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!

评价 0 条
prtyaaL2
粉丝 1 资源 1949 + 关注 私信
最近热门资源
银河麒麟桌面操作系统备份用户数据  125
统信桌面专业版【全盘安装UOS系统】介绍  120
银河麒麟桌面操作系统安装佳能打印机驱动方法  111
银河麒麟桌面操作系统 V10-SP1用户密码修改  105
最近下载排行榜
银河麒麟桌面操作系统备份用户数据 0
统信桌面专业版【全盘安装UOS系统】介绍 0
银河麒麟桌面操作系统安装佳能打印机驱动方法 0
银河麒麟桌面操作系统 V10-SP1用户密码修改 0
作者收入月榜
1

prtyaa 收益393.62元

2

zlj141319 收益218元

3

1843880570 收益214.2元

4

IT-feng 收益209.03元

5

风晓 收益208.24元

6

777 收益172.71元

7

Fhawking 收益106.6元

8

信创来了 收益105.84元

9

克里斯蒂亚诺诺 收益91.08元

10

技术-小陈 收益79.5元

请使用微信扫码

加入交流群

请使用微信扫一扫!