7-25学习笔记

一、锁对象  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     失败返回 falseif (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  CallableRunnable 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();
可以根据工作任务创建线程,如果没有新的线程就创建新的线程,队列中不放任务 线程存活时间60sExecutors.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.mzph.cn/web/49858.shtml

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

相关文章

Redis-数据的极速之旅(一)

Redis基础篇 Redis的自我介绍我的核心数据结构1.字符串&#xff08;String&#xff09;2.哈希&#xff08;Hash&#xff09;3.列表&#xff08;List&#xff09;4.集合&#xff08;Set&#xff09;5.有序集合&#xff08;Sorted Set&#xff09; 高性能原理1.Redis为什么快&…

B端系统UI个性化设计:感受定制之美

B端系统UI个性化设计&#xff1a;感受定制之美 引言 艾斯视觉作为ui设计和前端开发从业者&#xff0c;其观点始终认为&#xff1a;在当今竞争激烈的商业环境中&#xff0c;B端&#xff08;Business-to-Business&#xff09;系统的设计不再仅仅是功能性的堆砌&#xff0c;而是…

书生大模型实战营--L1关卡-OpenCompass 评测 InternLM-1.8B 实践

一、使用 OpenCompass 评测 internlm2-chat-1.8b 模型在 MMLU 数据集上的性能 1、使用lmdeploy部署 internlm2-chat-1.8b模型 2、根据OpenCompass官网教程安装并下载数据集 opencompass/README_zh-CN.md at main open-compass/opencompass GitHub 注意&#xff1a; pyhton…

JAVAWeb实战(前端篇)

项目实战一 0.项目结构 1.创建vue3项目&#xff0c;并导入所需的依赖 npm install vue-router npm install axios npm install pinia npm install vue 2.定义路由&#xff0c;axios&#xff0c;pinia相关的对象 文件&#xff08;.js&#xff09; 2.1路由(.js) import {cre…

当全球银行系统“崩溃”时会发生什么?

有句名言&#xff1a;“当美国打喷嚏时&#xff0c;世界就会感冒……”换句话说&#xff0c;当人们对美国及其经济稳定性的信心下降时&#xff0c;其他经济体&#xff08;以及黄金、白银和股票等资产&#xff09;的价值往往会下降。 与任何其他资产类别一样&#xff0c;加密货…

超详细-数据结构-二叉树概念及结构,堆的概念及结构以及堆的代码的c语言实现

本篇博客将详细讲述二叉树的概念&#xff0c;堆的概念及结构以及堆的代码实现&#xff0c;以及二叉树&#xff0c;堆的相关应用。Top K 问题&#xff0c;堆排序的实现以及二叉树链式结构的实现将在之后的博客更新。你可在目录中找到你想重点阅读的内容。堆的完整代码实现在文章…

【秋招笔试题】方程

解析&#xff1a;暴力枚举。建议用Python的eval函数,C手写略麻烦。 #include <iostream> #include <string> #include <vector> #include <sstream>using namespace std;long long stringResult(const string &expr) {vector<string> plusP…

visual studio性能探测器使用案列

visual studio性能探测器使用案列 在visual studio中&#xff0c;我们可以使用自带的工具对项目进行性能探测&#xff0c;具体如下 1.选择性能探查器 Vs2022/Vs2019中打开方式&#xff1a; Vs2017打开方式&#xff1a; 注意最好将解决方案配置为&#xff1a;Release Debu…

昇思25天学习打卡营第22天|CycleGAN图像风格迁移互换

相关知识 CycleGAN 循环生成网络&#xff0c;实现了在没有配对示例的情况下将图像从源域X转换到目标域Y的方法&#xff0c;应用于域迁移&#xff0c;也就是图像风格迁移。上章介绍了可以完成图像翻译任务的Pix2Pix&#xff0c;但是Pix2Pix的数据必须是成对的。CycleGAN中只需…

如何获得某个Window画面所属包名packageName和用户userId

在安卓上获得某个Window画面所属包名packageName和用户userId的方法 1&#xff0c;用到的工具如下&#xff1a; adb androidSDK里的monitor工具 adb shell dumpsys window animator adb shell dumpsys window命令 jdk 1.8已在安卓14模拟器上测试通过。 以AOSP的launcher中的m…

【.NET 6 实战--孢子记账--从单体到微服务】--开发环境设置

在这一小节&#xff0c;我们将设置开发环境。 一、安装SDK 咱们的项目使用的是 .NET6&#xff0c;开发前我们需要从官网上下载.NET6 SDK&#xff08;点击下载&#xff09;&#xff0c;这里要注意的是我们需要下载.NET6 SDK&#xff0c;而不是 .NET6 Runtiem 。SDK 包含 Runti…

C++静态成员变量和静态成员函数

演示代码如下&#xff1a; #include<iostream> using namespace std;class Person { public://静态成员函数 所有对象共享一个函数&#xff0c;且只能调用静态成员变量 ******static void func(){m_A 300;cout << "静态成员函数调用" << endl;}/…

【MySQL进阶之路 | 高级篇】简述Bin Log日志

1. 日志类型 MySQL有不同类型的日志文件&#xff0c;用来存储不同类型的日志&#xff0c;分为二进制日志、错误日志、通用查询日志和慢查询日志&#xff0c;这也是常用的4种。MySQL 8又新增两种支持的日志:中继日志和数据定义语句日志。使用这些日志文件&#xff0c;可以查看M…

openFeign实现服务间调用

以两个模块&#xff08;batch&#xff0c;business&#xff09;为例子&#xff0c;期望实现batch调用business中的hello接口 在主程序batch中引入pom文件 <!--远程调用openfeign--><dependency><groupId>org.springframework.cloud</groupId><arti…

Linux网络工具“瑞士军刀“集合

一、背景 平常我们在进行Linux服务器相关运维的时候&#xff0c;总会遇到一些网络相关的问题。我们可以借助这些小巧、功能强悍的工具帮助我们排查问题、解决问题。 下面结合之前的一些使用经验为大家介绍一下一些经典应用场景下&#xff0c;这个网络命令工具如何使用的。例如怎…

游泳馆押金原路退回源码解析

<dl class"list "><dd class"address-wrapper dd-padding"><div class"address-container"><cyberdiv style"color:#f0efed;font-size:14px;float:right;position:absolute;right:10px;top: 2px;">●●●<…

MYSQL 第三次作业

1、第三次作业 01、SELECT * FROM student; SELECT * FROM score; 02、SELECT * FROM student LIMIT 1, 3; 03、SELECT * FROM student WHERE department IN (计算机系, 英语系); 04、SELECT * FROM student WHERE birth_year > 1998; 05、SELECT department, COUNT(*) as c…

CSP-J模拟赛day1——解析+答案

题目传送门 yjq的吉祥数 题解 送分题&#xff0c;暴力枚举即可 Code #include<bits/stdc.h> using namespace std;int l,r; int num1,tmp0,q[10000],a[10000]; int k (int x){for (int j1;j<tmp;j){if (xq[j])return 0;}return 1; } int main(){while (num<100…

Linux Vim全能攻略:实战代码,轻松掌握文本编辑神器

1. Vim简介与安装 1.1 Vim的历史与发展 Vim&#xff08;Vi IMproved&#xff09;是一款高度可配置的文本编辑器&#xff0c;它起源于1976年由Bill Joy开发的Vi编辑器。Vi是Unix系统上最古老的文本编辑器之一&#xff0c;因其强大的功能和高效的编辑方式而广受欢迎。随着时间的…

Photos框架 - 自定义媒体选择器(UI预览)

引言 在前面的博客中我们已经介绍了使用媒体资源数据的获取&#xff0c;以及自定义的媒体资源选择列表页。在一个功能完整的媒体选择器中&#xff0c;预览自然是必不可少的&#xff0c;本篇博客我们就来实现一个资源的预览功能&#xff0c;并且实现列表和预览的数据联动效果。…