7-25学习笔记

news2025/2/24 22:19:49

一、锁对象  Lock接口

1、创建锁对象   ReentrantLock类

Lock lock=new ReentrantLock(true);
默认创建的是非公平锁  在创建锁对象时传入一个true参数  便会创建公平锁  先来后到
是重入锁  排他锁  加锁后不允许其它线程进入

2、加锁、解锁

(1)lock()  unlock()
public class EasyThreadB {
    Lock lock=new ReentrantLock(true);//创建锁对象
    public void mehtod(){
        lock.lock();//加锁
        System.out.println(Thread.currentThread().getName()+"进入方法");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread().getName()+"结束方法");
        lock.unlock();//解锁
    }

    public static void main(String[] args) {
        Runnable run=new EasyThreadB()::mehtod;
        Thread a=new Thread(run);
        Thread b=new Thread(run);
        a.start();
        b.start();

    }
}

(2)tryLock()
public class EasyThreadB {
    Lock lock=new ReentrantLock(true);//创建锁对象
    public void mehtod(){
        // lock.tryLock()//尝试加锁    加锁成功 true     失败返回 false
        if (lock.tryLock()){
            System.out.println(Thread.currentThread().getName()+"进入方法");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(Thread.currentThread().getName()+"结束方法");
            lock.unlock();//解锁
        }else {
            System.out.println("加锁未成功----------去执行别的代码");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            mehtod();
        }
    }

    public static void main(String[] args) {
        Runnable run=new EasyThreadB()::mehtod;
        Thread a=new Thread(run);
        Thread b=new Thread(run);
        a.start();
        b.start();

    }
}

  lock.tryLock()  尝试加锁    加锁成功 true     失败返回 false

 3、读写锁   ReentrantReadWriteLock类

        读锁(Read Lock):允许多个线程同时获得读锁,在没有写锁的情况下,多个线程可以并发地读取共享资源。

        写锁(Write Lock):独占锁,一次只允许一个线程获取写锁进行写操作,当有线程持有写锁时,其他线程无法获取读锁或写锁。

public class EasyTreadC {

    public static ReentrantReadWriteLock rrwl=new ReentrantReadWriteLock();

    public static void method(){
        System.out.println(Thread.currentThread().getName()+"进入方法");
        Lock lock=rrwl.readLock();
        lock.lock();
        System.out.println(Thread.currentThread().getName()+"加锁成功---读锁");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread().getName()+"方法结束");
        lock.unlock();
    }

    public static void methodWrite(){
        System.out.println(Thread.currentThread().getName()+"进入方法");
        Lock lock=rrwl.writeLock();
        lock.lock();
        System.out.println(Thread.currentThread().getName()+"加锁成功---写锁");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread().getName()+"方法结束");
        lock.unlock();
    }

    public static void main(String[] args) {
        Runnable run=EasyTreadC::method;
        Runnable runWrite=EasyTreadC::methodWrite;
        Thread a=new Thread(run);
        a.start();
        Thread b=new Thread(run);
        b.start();
        Thread c=new Thread(run);
        c.start();
        Thread d=new Thread(run);
        d.start();
        Thread e=new Thread(run);
        e.start();

        Thread f=new Thread(runWrite);
        f.start();
        Thread g=new Thread(runWrite);
        g.start();
        Thread h=new Thread(runWrite);
        h.start();
        Thread i=new Thread(runWrite);
        i.start();
        System.out.println("main线程结束---------");
    }
}

public class EasyThreadE {
    public static void main(String[] args) {
        EasyList list=new EasyList();
        Runnable runSize=()->{list.size();};
        Runnable runGet=()->{list.get(0);};
        Runnable runAdd=()->{list.add(12);};
        list.add(12);
        Thread a=new Thread(runSize);
        Thread b=new Thread(runGet);
        Thread c=new Thread(runAdd);
        a.start();b.start();c.start();
    }
}
class EasyList{
    private int[] values=new int[20];
    private int size=0;

    ReentrantReadWriteLock rwLock=new ReentrantReadWriteLock();

    public int size(){
        Lock readLock=rwLock.readLock();
        readLock.lock();
        System.out.println(Thread.currentThread().getName()+"Size开始");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread().getName()+"Size结束");
        readLock.unlock();
        return size;
    }

    public int get(int index){
        Lock readLock=rwLock.readLock();
        readLock.lock();
        System.out.println(Thread.currentThread().getName()+"Get开始");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        if(index>=size){
            throw new IndexOutOfBoundsException("index is "+index);
        }
        System.out.println(Thread.currentThread().getName()+"Get结束");
        readLock.unlock();
        return values[index];
    }

    public boolean add(int item){
        Lock writeLock=rwLock.writeLock();
        writeLock.lock();
        System.out.println(Thread.currentThread().getName()+"Add开始");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        if(size>=values.length){
            return false;
        }
        values[size++]=item;
        System.out.println(Thread.currentThread().getName()+"Add结束");
        writeLock.unlock();
        return true;
    }
}

4、 wait()与notify()、notifyAll()

notify():唤醒一条被该锁对象wait的线程  唤醒后线程在同步代码块外等待机会进入  进入后从
        之wait代码后开始执行
notifyAll():唤醒全部被该对象wait的线程
wait():让执行到该代码的线程进入等待状态(等待池) 结束等待状态后进入就绪状态
public class EasyThreadD {
  public static final  Object OBJ=new Object();

  public static void method(){
     System.out.println(Thread.currentThread().getName()+"进入方法");

     synchronized (OBJ) {
         OBJ.notify();
         OBJ.notifyAll();
         System.out.println(Thread.currentThread().getName() + "进入同步代码块");
         try {
             try {
                 System.out.println(Thread.currentThread().getName() + "进入等待状态");
                 OBJ.wait();
                 System.out.println(Thread.currentThread().getName() + "重新运行");
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
             }
             Thread.sleep(1000);
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         }
         System.out.println(Thread.currentThread().getName() + "结束同步代码块");
         OBJ.notify();
     }
  }

  public static void main(String[] args) {
     Runnable run=EasyThreadD::method;
     Thread a=new Thread(run);
     a.start();
     Thread b=new Thread(run);
     b.start();
     Thread c=new Thread(run);
     c.start();
     Thread d=new Thread(run);
     d.start();
  }
}

        wait和sleep的区别
    wait 是Object中定义的方法,可以让锁对象调用,让执行到该代码的线程进入到等待状态
    sleep是Thread类中定义的静态方法,可以让执行到该行的线程进入等待状态
    区别: 1 sleep需要传入一个毫秒数,到达时间后会自动唤醒
            wait不能自动唤醒,必须调用notify/notifyAll方法唤醒
         2 sleep方法保持锁状态进入等待状态    wait方法会解除锁的状态,其他线程可以进入
           运行

二、线程池  ThreadPoolExecutor类

        池==重用        完成线程创建和管理、销毁工作

1、线程池对象执行Runnable 和Callable

        线程任务   Runnable   Callable
        Callable只能用submit()添加执行

        ThreadPoolExecutor类的方法   
        添加执行线程任务 execute(Runnable  run) submit(Callable call) submit(Runnable  run)
        submit()有返回值  返回值与call的泛型相同

        关闭线程池对象  shutdown()

public class EasyExecuters {
    public static void main(String[] args) throws ExecutionException, 
InterruptedException {
        BlockingQueue qu=new ArrayBlockingQueue(12);
        ThreadPoolExecutor tpe=new ThreadPoolExecutor(5,10,10,
                TimeUnit.SECONDS,qu,Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());

        //线程任务  Runnable  Callable
        Runnable run=EasyExecuters::method;
        tpe.execute(run);

        Callable<String> call=EasyExecuters::methodCall;
        Future<String> f=tpe.submit(call);
//        tpe.execute(call);//Callable只能用submit提交
//        tpe.submit(run);
        System.out.println(f.get());//会等待线程执行完毕

        //关闭线程池对象
        tpe.shutdown();
    }
    public static void method(){
        System.out.println(Thread.currentThread().getName()+"执行代码");
    }
    public static String methodCall() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"执行代码call");
        Thread.sleep(2000);
        return "callResult";
    }
}

2、Future类

        Future是 Java 中一个用于表示异步计算结果的接口。它主要用于处理那些可能需要较长时间运行的任务,使得主线程可以继续执行其他工作,而无需等待任务完成。

Future<T> f=tpe.submit(call);

方法:

        cancel(boolean mayInterruptIfRunning): 尝试取消任务的执行。
        isCancelled(): 判断任务是否被取消。
        isDone(): 判断任务是否已经完成。
        get(): 获取任务的结果,如果任务尚未完成则阻塞。
        get(long timeout, TimeUnit unit): 在指定时间内获取任务的结果,如果超时则抛出
                                                TimeoutException。

Future 的工作机制

        当我们提交一个任务到线程池时,线程池会返回一个 Future 对象,通过这个对象可以控制任务的执行状态,并在任务完成后获取结果。

 3、线程池7个参数

        (1)核心线程数 
        (2)最大线程数 
        (3)保持存活时间 
        (4)保持存活时间的时间单位(TimeUnit.SECONDS)秒 
        (5)工作队列BlockingQueue接口 
        (6)线程工厂(Executors.defaultThreadFactory())
        (7)回绝策略(new ThreadPoolExecutor.AbortPolicy())

 4、四种回绝策略

AbortPolicy (默认)放弃该任务并会抛出一个异常RejectedExecutionException
CallerRunsPolicy 调用者执行,让传递任务的线程执行此任务
DiscardOldestPolicy 放弃队列中时间最长的任务,将新任务加入队列,不会抛出异常
DiscardPolicy 直接放弃新的任务,不会抛出异常

5、 线程池的工作原理

任务放置在工作队列中
 1>池中是否有空闲的线程,若有让该线程执行任务
 2>如果池中没有空闲的线程,判断池中的线程数量有没有达到核心线程数
 3>如果没有达到,创建新的线程执行任务,如果已经达到,优先在队列中存储,直到队列填满
 4>工作队列填满后再添加新的任务,判断是否达到最大线程数,如果没有,创建新的线程执行任务
   直到填满最大线程数
 5>已经填满最大线程数,队列也已经填满,没有空闲的线程,就执行回绝策略
 6>线程池中的线程达到(超过)核心线程数,超出的数量会根据存活时间,进行销毁,直到数量达到核
   心线程数,如果线程数少于核心线程数,不会消亡

6、 java中内置的线程池对象

Executors.newCachedThreadPool();
可以根据工作任务创建线程,如果没有新的线程就创建新的线程,队列中不放任务 线程存活时间60s

Executors.newFixedThreadPool(10);
设定最大线程数量的线程池

Executors.newScheduledThreadPool(10);
提供定时运行的处理方案

Executors.newSingleThreadExecutor();
创建一个具有单个线程的线程池 保障任务队列完全按照顺序执行

三、枚举类

         默认继承Enum 但不能用extents声明,只能用enum声明

        首行 必须枚举所有的实例
        不可序列化  不可克隆

public enum EasyColor {
    RED,YELLOW,GREEN,BLUE,PINK;

    public void printColor(){
        System.out.println(this.name());
        System.out.println(this.ordinal());
    }
}

测试类 

class Test{
    public static void main(String[] args) {
        EasyColor.GREEN.printColor();
    }
}

四、死锁

        死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。当多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进,这种情况就是死锁。

 1、死锁产生的四个必要条件

(1)互斥条件

        进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。

(2)不剥夺条件

        进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放(只能是主动释放)。

(3)请求和保持条件

        进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。

(4)循环等待条件 

        存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被链中下一个进程所请求。

 2、避免死锁

(1)破坏“请求和保持”条件

  想办法,让进程不要那么贪心,自己已经有了资源就不要去竞争那些不可抢占的资源。比如,让进程在申请资源时,一次性申请所有需要用到的资源,不要一次一次来申请,当申请的资源有一些没空,那就让线程等待。不过这个方法比较浪费资源,进程可能经常处于饥饿状态。还有一种方法是,要求进程在申请资源前,要释放自己拥有的资源。

(2)破坏“不可抢占”条件

  允许进程进行抢占,方法一:如果去抢资源,被拒绝,就释放自己的资源。方法二:操作系统允许抢,只要你优先级大,可以抢到。

(3)破坏“循环等待”条件

  将系统中的所有资源统一编号,进程可在任何时刻提出资源申请,但所有申请必须按照资源的编号顺序(升序)提出

3、死锁解决方法

      在有些情况下死锁是可以避免的。以下是避免死锁的技术:

(1)加锁顺序

        线程按照一定的顺序加锁

(2)加锁时限

        线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁

(3)死锁检测

       步骤一:每个进程、每个资源制定唯一编号

  步骤二:设定一张资源分配表,记录各进程与占用资源之间的关系

  步骤三:设置一张进程等待表,记录各进程与要申请资源之间的关系

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1954185.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

服务器搭建总结

服务器搭建好初期要记得开放端口&#xff0c;配置安全组 &#xff0c;主要的有22&#xff0c;80&#xff0c;3389&#xff0c;8888等&#xff0c;宝塔连接的端口在8888上&#xff0c;不开放无法连接 由于时使用的腾讯云服务器&#xff0c;所以在宝塔选择上使用了Windows的面板…

Autodesk Revit v2025 激解锁版下载及安装教程 (三维建模软件)

前言 Revit是欧特克公司知名的三维建模软件&#xff0c;是建筑业BIM体系中使用最广泛的软件之一&#xff0c;其核心功能是三维建筑模型参数化设计、渲染效果图、算量&#xff0c;土建建模、机电建模、用来帮助工程师在施工前精确模拟阶段。 一、下载地址 下载链接&#xff1…

消息摘要算法:MD5加密

&#x1f31f; 主题简介 今天&#xff0c;我们将深入探讨一种经典且广泛应用的加密算法——MD5。通过案例形式了解其原理、实现方法及注意细节。无论你是Python爱好者还是JavaScript高手&#xff0c;这篇内容都将为你揭开MD5的神秘面纱。 &#x1f4da; 内容介绍 MD5&#xf…

大话成像公众号文章阅读学习(一)

系列文章目录 文章目录 系列文章目录前言一、扫射拍摄二、索尼Alpha 9 III2.1. 视频果冻效应2.2 闪光灯同步速度2.3 其他功能 三 A9III 局限性总结 前言 大话成像是一个专注成像的公众号&#xff0c;文章都很好。 今天看的这篇是 特朗普遭枪击后“大片”出自它 文章地址 htt…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑电动汽车动态拥堵的配电网灵活性资源双层优化调度 》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

揭秘企业为何钟情定制红酒:品牌形象与不同的礼品的双重魅力

在商务世界的广阔天地里&#xff0c;红酒不仅仅是一种饮品&#xff0c;更是一种传递情感、展示品味的不同媒介。近年来&#xff0c;越来越多的企业开始钟情于定制红酒&#xff0c;其中洒派红酒&#xff08;Bold & Generous&#xff09;通过其品质和个性化的定制服务&#x…

深入源码:解析SpotBugs (4)如何自定义一个 SpotBugs plugin

自定义一个 spotbugs 的插件&#xff0c;官方有比较详细的说明&#xff1a; https://spotbugs.readthedocs.io/en/stable/implement-plugin.html 本篇是跟随官网demo的足迹&#xff0c;略显无聊&#xff0c;可跳过。 创建工程 执行maven 命令 mvn archetype:generate -Darche…

关于Jenkins自动化部署Maven项目:

jenkins介绍: Jenkins是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0c;旨在提供一个开放易用的软件平台&#xff0c;使软件项目可以进行持续集成。 jenkins作用:更好的利于测试工程师测试项目(自动部署) 安装je…

游戏UI设计大师课:3款游戏 UI 设计模板

很多时候&#xff0c;做设计需要找素材。假如是普通的 UI 界面或者 Banner 等等&#xff0c;在Dribbble、Pinterest、即时设计、Behance 翻看这样的网站&#xff0c;至少可以梳理出一些想法和思路。如果你需要一个更规范的指南&#xff0c;此时&#xff0c;在各种设计规范、官方…

【网络安全】AWS S3 Bucket配置错误导致敏感信息泄露

未经许可&#xff0c;不得转载。 文章目录 前言技术分析正文 前言 AWS&#xff08;Amazon Web Services&#xff09;是亚马逊公司提供的一个安全的云服务平台&#xff0c;旨在为个人、公司和政府机构提供计算能力、存储解决方案、内容交付和其他功能。作为全球领先的云服务提供…

electron调试

electron 调试 electron 的调试分两步&#xff0c;界面的调试&#xff0c;和主进程的调试。 界面调试类似浏览器F12&#xff0c;可是调试不到主进程。 主进程调试有vscode、命令行提示和外部调试器调试。 本篇记录的练习是vscode调试。命令行和外部调试器的方式可以参考官网&a…

模拟实现c++中的vector模版

目录 一vector简述&#xff1a; 二vector的一些接口函数&#xff1a; 1初始化&#xff1a; 2.vector增长&#xff1a; 3vector增删查改&#xff1a; 三vector模拟实现部分主要函数&#xff1a; 1.size,capacity,empty,clear接口&#xff1a; 2.reverse的实现&#xff1…

青少年科普平台-计算机毕业设计源码76194

摘 要 对于搭建一个青少年科普平台&#xff0c;您可以考虑使用Spring Boot作为后端框架。Spring Boot是一个能够简化Spring应用开发的框架&#xff0c;能够帮助您快速搭建稳定、高效的后端服务。您可以利用Spring Boot的特性来构建一个可靠的数据服务&#xff0c;用于展示和传播…

docker镜像下载

1、搜索镜像 [rootlocalhost ~]# docker search ubuntu 2、下载ubuntu系统镜像(容器架构与宿主机相同) [rootlocalhost ~]# docker pull ubuntu #选择stars值最高镜像下载&#xff0c;默认为latest版 [rootlocalhost ~]# docker images 3、查看镜像支持的架构 [rootlocalh…

1143. 最长公共子序列(详细版)

目录 dp解法&#xff1a; 1.状态代表什么&#xff1a; 2. 状态转移方程 3.初始化 3. so为什么要这样&#xff1f; 代码实现&#xff1a; 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0…

protobuf2.5升级protobuf3.14.0

这个升级搞得心力憔悴&#xff0c;我VS2010升级到了VS2017&#xff0c;所有的库都要编译一下&#xff0c;想着顺便把其他的三方库也升级了。搞了好几天&#xff0c;才升级完&#xff0c;因为不仅要搞windows还要搞linux版本各种库的升级。hpsocket的升级&#xff0c;jsoncpp的升…

stm32h7串口发送寄存器空中断

关于stm32串口的发送完成中断UART_IT_TC网上资料挺多的&#xff0c;但是使用发送寄存器空中断UART_IT_TXE的不太多 UART_IT_TC 和 UART_IT_TXE区别 UART_IT_TC 和 UART_IT_TXE 是两种不同的 UART 中断源&#xff0c;用于表示不同的发送状态。它们的主要区别如下&#xff1a; …

安卓单机游戏:龙之矛内置菜单,【免费分享】白嫖!

龙之矛是一款传统的横版卷轴RPG游戏。在游戏中玩家将探索被梦魇蹂躏的世界&#xff0c;和朋友一起猎杀强大的BOSS&#xff0c;如果你杀死了boss&#xff0c;那么你可以制作具有boss力量的装备。游戏内所有装备都有独特的外观&#xff0c;你可以用各种华丽的装备打扮你的角色。英…

并发基础——Java全栈知识(37)

1、并发基础 1、进程和线程的区别 程序由指令和数据组成&#xff0c;但这些指令要运行&#xff0c;数据要读写&#xff0c;就必须将指令加载至 CPU&#xff0c;数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的。当…

【LLM】-10-部署llama-3-chinese-8b-instruct-v3 大模型

目录 1、模型下载 2、下载项目代码 3、启动模型 4、模型调用 4.1、completion接口 4.2、聊天&#xff08;chat completion&#xff09; 4.3、多轮对话 4.4、文本嵌入向量 5、Java代码实现调用 由于在【LLM】-09-搭建问答系统-对输入Prompt检查-CSDN博客 关于提示词注入…