多线程与高并发(一)

article/2024/4/13 13:31:42

【前言】:

多线程、JVM、操作系统。

【概述】:

基础概念
JUC同步工具
同步容器
Disruptor //一个MQ框架,公认的单机环境下效率最高。
线程池

【线程的概念】:

【纤程】:在这里插入图片描述

【 run和start的区别 】:

        //new T1().run();    //方法调用。new T1().start();    //Thread类里面有start方法。

run方法还是依次顺序执行;( 先run后main , 相当于只有一条执行路径 )
但start方法是分支执行。( 有分支路径 )

【 线程的启动方式 】:

package Ten_Class.t01;import java.util.concurrent.*;public class T02_HowToCreateThread {static class MyThread extends Thread {@Overridepublic void run() {System.out.println("Hello MyThread!");}}static class MyRun implements Runnable {@Overridepublic void run() {System.out.println("Hello MyRun!");}}static class MyCall implements Callable<String> {@Overridepublic String call() {System.out.println("Hello MyCall");return "success";}}//启动线程的5种方式public static void main(String[] args) throws Exception {new MyThread().start();new Thread(new MyRun()).start();new Thread(() -> {System.out.println("Hello Lambda!");}).start();FutureTask<String> task = new FutureTask<>(new MyCall());Thread t = new Thread(task);t.start();System.out.println(task.get());ExecutorService service = Executors.newCachedThreadPool();service.execute(() -> {System.out.println("Hello ThreadPool");});Future<String> f = service.submit(new MyCall());String s = f.get();System.out.println(s);service.shutdown();}
}

【 线程的方法 】:

【 sleep 】:

睡眠 ,当前线程暂停一段时间, 让给别的线程去运行。

【 yield 】:

我从CPU上先离开 , 进入到一个等待队列里。当然有可能刚进去就被拽出去执行 , 但更大的可能是——将等待队列中其他的拽出去执行。
我让出一下CPU , 然后从等待队列里拽出一个来执行。

【 Join 】:

在这里插入图片描述
两个线程 t1 、 t2 , 如果在t1线程的某个点上调用 t2.join , 这个点的意思是——立即跑到t2去运行,t1先等着,什么时候t2运行完了,t1再运行 。
在这里插入图片描述
//Join常用来用于等待另一个线程的结束。

【如何保证三个线程按照顺序执行完呢?】:

main{t1.join();t2.join();t3.join();
}或者t1{t2.join();
}t2{t3.join();
}

【 线程的状态 】:

【NEW】:

在这里插入图片描述
//当我们新建了一个线程,new了一个,还没有调用start( ) 方法之前的线程的状态。

【 Runnable 】:

//当你调用start方法之后 , 它会被线程调度器来执行,也就是交给操作系统来执行了。交给操作系统来执行的话,整个的状态叫做——Runnable。Runnable内部又有两个状态( Ready就绪状态 和 Running运行状态 ) , Ready就绪状态是指我们扔到CPU的等待队列里去了。真正的扔到CPU上去运行了——这个状态叫做Running。
Teminated状态后,不能再回到NEW状态再调用start()了,这样是不行的。
在这里插入图片描述
【什么时候进入阻塞?】:
加synchronized进入同步代码块,我这段代码写了synchronized , 但是我还没有得到那把锁 。
在这里插入图片描述
【 哪些是操作系统管理的?哪些是JVM管理的? 】:
全是JVM管理的 ,因为JVM管理这些状态的时候也要通过操作系统。JVM 和 操作系统 它俩分不开 , JVM是跑在操作系统上的程序。

【锁的概念】:

package Ten_Class.t01;public class T_114_01 {private int count = 10;private Object o = new Object();public void m(){synchronized ( o ){count--;System.out.println( Thread.currentThread().getName() + " count = " +count );}}
}

【 锁的特性 】:

如果我们每一次都定义一个锁的对象( Object o )的话,这样的加锁方式太麻烦,每次都得New一个新的对象出来。
//所以有一个最简单的方式:

        synchronized (this){  //锁定当前方法。。。。。。。}

【Class文件】:
每一个class文件load到内存之后,它会专门生成一个class类的对象——和load到内存的那一段代码相对应;

【 方法上加sync 】:

package Ten_Class.t01;public class T_115_02 {private static int count = 10;public synchronized static void m(){   //这里等同于synchronized (T_115_02.class)count--;System.out.println( Thread.currentThread().getName() + " count = " + count );}
}

【 设计小程序验证锁的问题 】:

【规则】:
加了synchronized就没有必要再加volatile了,因为synchronized既保证了原子性又保证了可见性。

【同步方法和非同步方法是否可以同时调用?】:
//下面程序段中m1是同步方法,m2是非同步方法。

/*** 对比前一个小程序,分析一下这个程序的输出*/package Ten_Class.t01;public class T_116_02 {private int count = 10;public synchronized void m1() {System.out.println( Thread.currentThread().getName() + " m1 start...... " );try{Thread.sleep(10000 );}catch( InterruptedException e ){e.printStackTrace();}System.out.println( Thread.currentThread().getName() + " m1 end 。。。。。" );}public void m2(){try{Thread.sleep(5000 );}catch (InterruptedException e){e.printStackTrace();}System.out.println( Thread.currentThread().getName() + " m2 " );}public static void main(String[] args) {T_116_02 t = new T_116_02();new Thread( t::m1 , "t1" ).start();new Thread( t::m2 , "t2" ).start();}
}

在这里插入图片描述
//说明是允许被同时调用的。

【模拟银行账户 】:

//是否允许客户读取那些不好的数据。
【允许客户读到不好数据】:
写方法加锁,读方法可以不加锁。
【不允许客户读取不好的数据】:
写、读 方法都加上锁。

/*** 面试题:模拟银行账户* 对业务写方法加锁* 对业务读方法不加锁* 这样行不行?* <p>* 容易产生脏读问题(dirtyRead)*/package Ten_Class.t01;import java.util.concurrent.TimeUnit;/*
* 【面试题】————模拟银行账户
* 对业务写方法加锁;
* 对业务读方法不加锁;
* 这样行不行?
*
* 容易产生脏读问题( dirtyRead )
* */public class T_116_03_Account {String name;double balance;public synchronized void set(String name, double balance) {this.name = name;try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}this.balance = balance;}public /*synchronized*/ double getBalance(String name) {return this.balance;}public static void main(String[] args) {T_116_03_Account a = new T_116_03_Account();new Thread(() -> a.set("zhangsan", 100.0)).start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(a.getBalance("zhangsan"));try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(a.getBalance("zhangsan"));}
}

【 加锁与否 】:

能不加锁就不加锁 , 加完锁后的效率要低100倍。

【锁的可重入属性】:

synchronized必须是可重入锁;

【例一】:

package Ten_Class.t01;import java.util.concurrent.TimeUnit;/*
* 一个同步方法可以调用另外一个同步方法,一个线程已经拥有某个对象的锁,再次申请的时候仍然会得到该对象的锁。
* 也就是说synchronized获得的锁是可重入的。
* */public class T_117_01 {synchronized void m1(){System.out.println("m1 start");try{TimeUnit.SECONDS.sleep(1);}catch (InterruptedException e ){e.printStackTrace();}m2();System.out.println("m1 end");}synchronized void m2(){try{TimeUnit.SECONDS.sleep(2);}catch (InterruptedException e ){e.printStackTrace();}System.out.println("----m2----");}public static void main(String[] args) {new T_117_01().m1();}
}

【例二】:

package Ten_Class.t01;import java.util.concurrent.TimeUnit;public class T_117_02 {synchronized void m(){System.out.println("m start");try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedException e){e.printStackTrace();}System.out.println("m end");}
}class TT extends T_117_02{synchronized void m(){System.out.println("child m start");super.m();System.out.println("child m end");}
}

【异常】:

//抛出异常,释放锁,其它想要拿到这把锁的程序会进来。

package Ten_Class.t01;import java.util.concurrent.TimeUnit;/*
* 程序在执行过程中,如果出现异常,默认情况锁会被释放;
* 所以,在并发处理的过程中,有异常要多加小心,不然可能会发生不一致的情况;
* 比如,在一个 web app 处理过程中 , 多个servlet线程共同访问一个资源,这时如果异常处理不合适,
* 在第一个线程中抛出异常,其它线程就会进入同步代码区,有可能会访问到异常产生时的数据。
* 因此要非常小心的处理同步业务逻辑中的异常。
* */
public class T_118_01 {int count = 0;synchronized void m(){System.out.println( Thread.currentThread().getName() + " start " );while (true){count++;System.out.println( Thread.currentThread().getName() + " count = " + count );try{TimeUnit.SECONDS.sleep(1);}catch ( InterruptedException e ){e.printStackTrace();}if (count==5){int i = 1/0;  //此处抛出异常 , 锁将要被释放,要想不被释放,可以在这里进行catch , 然后让循环继续。System.out.println( i );}}}public static void main(String[] args) {T_118_01 t = new T_118_01();Runnable r = new Runnable() {@Overridepublic void run() {t.m();}};new Thread( r,"t1").start();try{TimeUnit.SECONDS.sleep(3);}catch (InterruptedException e){e.printStackTrace();}new Thread(r,"t2").start();}
}

在这里插入图片描述


http://www.ngui.cc/article/show-738622.html

相关文章

嵌入式:ARM体系结构详解

文章目录指令集与指令集架构主要计算机指令集架构PC及服务器领域嵌入式领域新生代ARM体系结构的演变ARM发展的历程指令集与指令集架构 指令&#xff1a;就是指挥计算机工作的命令&#xff0c;程序就是一系列按一定顺序排列的指令&#xff0c;计算机就是通过执行程序中的指令来…

python | 第九章:python计算生态概览

本篇文章是对北京理工大学嵩天老师的《Python语言程序设计》第九章内容的学习笔记。 方法论&#xff1a;纵览python计算生态&#xff08;主要是第三方库介绍及应用场景&#xff09; 实践能力&#xff1a;初步编写带有计算生态的复杂程序。 1 从数据处理到人工智能 1.1 数据…

Matplotlib学习笔记(第二章 2.11使用指南 一些简单的例子)

第二章 学习指南 本页包含更多使用Matplotlib的深入指南。它分为初级、中级和高级部分&#xff0c;以及涵盖特定主题的部分。 有关较短的示例&#xff0c;请参阅我们的示例页面。您还可以在我们的用户指南中找到外部资源和FAQ。 2.1介绍 这些教程涵盖了使用Matplotlib创建可…

LaTeX页眉页脚自定义【有图有代码】

LaTeX页眉页脚自定义【有图有代码】一、自定义页眉页脚示例【双页文档】\fancyhead \fancyfoot1、代码讲解2、自定义代码3、页眉和页脚的装饰线4、总页数二、自定义页眉页脚示例【单页文档】\rhead \rfoot三、\pagestyle{}介绍四、设置当前页面样式\thispagestyle{}平时在写报告…

一文学会所有Web应用安全知识点

据调查大部分网络安全事故是软件缺陷导致的网络攻击。由于应用程序代码漏洞和安全漏洞&#xff0c;我们的企业正在遭受越来越多的攻击。调查显示攻击者可以通过盗用凭证&#xff0c;攻击10个测试过的web应用程序中的9个&#xff0c;进行恶意软件注入以及网络钓鱼攻击。因此&…

Oracle分区键值存在空值如何建分区表

maxvalue&#xff0c; 空值是无限大值 要存储分区键为空值的记录&#xff0c;那么就得有一个特定的分区来存储分区键为空值的记录。 1.Range-Partitioned Table 我们知道范围分区可以建values less than (maxvalue) SQL> CREATE TABLE sales ( prod_id NUMBER(6) , cust_id …

u-BOOT启动流程

1、u-boot入口&#xff1a;入口即第一行程序&#xff0c;程序的链接是由链接脚本决定的&#xff0c;编译uboot之后&#xff0c;可以在根目录下生成u-boot.lds文件 打开lds文件可以看到代码当前入口点&#xff1a; &#xff1a;_start&#xff0c;_start后面就是中断向量表&…

内网穿透代理服务器nps使用初探(三)微信小程序内网穿透

一、前言 已完成NPS 的部署,部署教程请参照:https://gaoming.blog.csdn.net/article/details/128203454 二、环境说明 2.1 内网客户端 内网IP系统内核192.168.1.113win11windows_amd64_client2.2 公网服务端 公网IP系统内核39.97.238.139CentOSlinux_amd64_server三、微信…

ATTCK-T1078-001-默认账户

0x01基础信息 具体信息详情ATT&CK编号T1078-001所属战术阶段初始访问操作系统windows 7 旗舰版 SP1创建时间2022年11月10日监测平台火绒安全、火绒剑、sysmon 0x02技术原理 攻击者可能会获取和滥用默认帐户的凭据&#xff0c;以作为获得初始访问、持久性、特权升级或防御…

汇编语言与微机原理 期末半开卷复习整理(下)

输入输出 8086采用I/O端口独立编址 in AL/AX,imm8/DX out imm8/DX,AL/AX 大于0FFH的端口只能存在DX 读外设(查询) status:in al,dxtest al,80H;//测标志位jz statusmov dx,100hin al,dx写外设&#xff08;查询&#xff09; status:mov dx,102Hin al,dxtest al,80Hjnz status…