多线程与高并发(一)

news2024/11/15 7:19:44

【前言】:

多线程、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 {
        @Override
        public void run() {
            System.out.println("Hello MyThread!");
        }
    }

    static class MyRun implements Runnable {
        @Override
        public void run() {
            System.out.println("Hello MyRun!");
        }
    }

    static class MyCall implements Callable<String> {
        @Override
        public 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() {
            @Override
            public 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.coloradmin.cn/o/69561.html

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

相关文章

[附源码]Python计算机毕业设计SSM家用饰品在线销售系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【面试问题】进程和线程的区别——通俗易懂

1. ”进程“是什么1.2 管理进程1.3 内存管理1.4 进程间通信2. 线程是什么3.进程和线程的区别1. ”进程“是什么 在对比"进程"和"线程"两者之间的区别前,我们需要先了解什么是"进程"?什么是"线程"? **“进程”(process)也叫"任…

HIFI测序揭示拟南芥MSH1参与介导的细胞器基因组重组与变异积累规律

近日&#xff0c;中国农业科学院农业基因组所武志强课题组在《The Plant Journal》在线发表了题为“Long-read sequencing characterizes mitochondrial and plastid genome variants in Arabidopsis msh1 mutants”的研究论文&#xff0c;该研究通过高精度的长读长测序&#x…

安卓APP源码和设计报告——仿淘宝水果商城

项目名称 仿淘宝水果商城项目概述 随着互联网技术地高速发展&#xff0c;计算机进入到每一个人的生活里&#xff0c;从人们的生活方式到整个社会的运转都产生了巨大的变革&#xff0c;而在信息技术发达的今天&#xff0c;互联网的各种娱乐方式都在渗透到人们的生活方式之中&…

Procreate绘画教程

Procreate绘画教程 从 30 多年的设计师/插画家那里彻底有效地学习 Procreate&#xff01;已更新至 Procreate 5.2&#xff01; 课程英文名&#xff1a;Procreate Solid Foundations 此视频教程共10.0小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印&#xff0c;源码…

三条建议!让您在世界杯期间确保网络安全!

2022年11月&#xff0c;全球的目光都聚焦在依旧“夏日炎炎”的卡塔尔。随着人们观看、分享赛事的习惯从传统的电视转为网络&#xff0c;世界杯必将成为整个2022年的“流量王”。在我国&#xff0c;仅仅德国与日本的一场比赛在微博平台就带来了13.8亿次阅读。 据估计&#xff0…

细粒度图像分类论文研读-2020

文章目录Filtration and Distillation: Enhancing RegionAttention for Fine-Grained Visual Categorization(by localization- classification subnetwork)AbstractIntroductionApproachDiscriminative Regions ProposingFeature Learning and Recognition EnsembleFiltration…

Spring源码深度解析:十一、Spring的循环依赖

一、前言 文章目录&#xff1a;Spring源码深度解析&#xff1a;文章目录 这篇文章是接着 Spring源码深度解析&#xff1a;七、bean的加载① - doGetBean 的继续分析过程。 二、什么是循环依赖 循环依赖&#xff0c;其实就是循环引用&#xff0c;就是两个或者两个以上的 bea…

【MySQL】数据处理函数

只有当你开始相信自己时&#xff0c;你才拥有真正的人生。——《洛奇》 前言&#xff1a; 大家好&#xff0c;我是爱打拳的程序猿。今天给大家展示是数据处理函数的用法&#xff0c;分为单行处理函数和分组函数。数据处理函数主要是为了更方便解决数据的各种问题。文章以代码和…

2023年Unity UI教程

2023年Unity UI教程 Unity 新 UI 系统 UI 工具包的完整概述 课程英文名&#xff1a;Modern Unity UI with UI Toolkit 此视频教程共10.0小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印&#xff0c;源码附件全 下载地址 课程编号&#xff1a;336 百度网盘地址&am…

SSM框架-获取容器的方式

9 容器 9.1 获取容器 记载类路径下的容器所在的配置文件,也就是之前用的 public class App2 {public static void main(String[] args) {ApplicationContext ctx new ClassPathXmlApplicationContext("applicationContext.xml");BookDao bookDao (BookDao) ctx.…

liunx 部署 kkfileview文件预览 以及解决https访问

kkfileview gitee地址 https://gitee.com/kekingcn/file-online-preview 1.下载office组件 wget https://kkfileview.keking.cn/LibreOffice_7.1.4_Linux_x86-64_rpm.tar.gz tar -zxvf LibreOffice_7.1.4_Linux_x86-64_rpm.tar.gz cd LibreOffice_7.1.4.2_Linux_x86-64_rpm/R…

TensorRT推理手写数字分类(一)

系列文章目录 &#xff08;一&#xff09;使用pytorch搭建模型并训练 文章目录系列文章目录前言一、网络搭建1.LeNet网络结构2.pytorch代码二、网络训练1.pytorch代码2.结果展示三、保存和加载模型1.保存整个网络2.保存网络中的参数总结前言 为了学习一下使用TensorRT进行推理…

硬核!Github星标79.4K的阿里强推Java面试参考指南到底有多强?

谈到Java面试&#xff0c;相信大家第一时间脑子里想到的词肯定是金三银四&#xff0c;金九银十。好像大家的潜意识里做Java开发的都得在这个时候才能出去面试&#xff0c;跳槽成功率才高&#xff01;但LZ不这么认为&#xff0c;LZ觉得我们做技术的一生中会遇到很多大大小小的面…

Java并发编程—如何写好代码?链式调用该怎么玩?

目录 一、案例说明 二、原生方式代码流程 三、链式调用代码流程 四、链式调用手搓的方式&#xff1a; 五、总结&#xff1a; 在上一篇博客https://blog.csdn.net/qq_52545155/article/details/128212148?spm1001.2014.3001.5501&#xff0c;博主在写商城统计商品价格的时…

mybatis中其他数据源也使用XML进行操作(SqlSessionFactory.openSession(Connection connection)方法)

文章目录1. 前言2. 先说结论3. 例子1. 准备数据2. 思考过程3. 结论1. 前言 当前在使用springbootmybatis的时候&#xff0c;通常会先在配置文件中配置好数据源&#xff0c;并在Mapper.xml文件编写好相关SQL&#xff0c;使用mybatis进行对数据库进行所谓的crud操作。 有时候会出…

nginx代理https妈妈级手册

目录 背景说明 相关地址 https证书生成 nginx安装及配置 结果展示​编辑 背景说明 为了保证传输加密、访问安全&#xff0c;我们采用nginx服务器将http服务代理为https。所需材料&#xff1a;openssl&#xff08;用来生成证书&#xff09;、http服务、nginx自身。 相关地址…

C/C++第三方库zeromq、log4cpp交叉编译、本地安装ubuntu180.04

一、zeromq的编译安装 1&#xff09;ubuntu下命令 apt-get install libzmq3-dev不推荐这种方式&#xff0c;因为很可能安装的版本并不是最新的&#xff1b; 2&#xff09;自己编译安装&#xff08;推荐&#xff09; 地址&#xff1a;https://github.com/zeromq/libzmq/relea…

设计模式--装饰者模式

文章目录前言一、未使用设计模式二、装饰者模式1.定义2.角色三、应用场景四、优缺点优缺前言 晓子&#xff08;咖啡店员&#xff09;&#xff0c;来一杯美式&#xff0c;加点威士忌和砂糖。 抱歉啊&#xff0c;猫。收银系统还没有你说的组合&#xff0c;要不换一个&#x1f60…

React 的调度系统 Scheduler

大家好&#xff0c;我是前端西瓜哥。今天来学习 React 的调度系统 Scheduler。 React 版本为 18.2.0 React 使用了全新的 Fiber 架构&#xff0c;将原本需要一次性递归找出所有的改变&#xff0c;并一次性更新真实 DOM 的流程&#xff0c;改成通过时间分片&#xff0c;先分成一…