Java线程、Java多线程详细介绍

2023-05-16

目录

一、进程和线程的区别

   1.1 进程

   1.2 线程

二、并发和并行

   2.1 并行

   2.2  并发

   2.3 监控线程的执行情况

三、创建方式

3.1 继承Thread类          

思考:为什么不直接通过对象调用start()方法?

3.2 实现Runnable接口

3.3 使用Callable创建线程

3.4 Callable 和 Runnable的区别

继承Thread和实现Runnable接口两种方法的区别

3.5使用线程池例如Executor框架

3.5.1  概念

3.5.2  好处

3.5.3  线程池执行基本原理

3.5.4  线程池创建方式

3.5.5 线程池的分类

3.5.6 线程池的核心参数

四、常用方法

五、多线程实现方案

六、线程终止

七、常用方法

 八、线程的生命周期

8.1 线程的状态

8.2 wait()、notify()、notifyAll()类比

九、 线程安全

 9.1 安全问题原因​编辑

 9.2  synchronized

  9.3 Lock

  9.4 线程锁

  9.5 并发工具类  ConcurrentHashMap HashMap HashTable

           9.6 线程死锁

           9.7 释放锁

十、思考题

1.volatile关键字

2.count++ 是不是原子操作

3.怎么保证原子操作

4.原子类原理--CAS原理

5.ConcurrentHashMap HashMap 和HashTbale的区别



一、进程和线程的区别


   1.1 进程

        操作系统中正在运行的软件,比如我们使用的QQ,就启动了一个进程,操作系统就为该进程分配了新的内存空间,进程具有独立性,动态性和并发性

  1. 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位
  2. 动态性:进程的实质是程序的一次执行过程,进程是动态产生的,动态是消亡的
  3. 并发性:任何进程都可以同其它进程一起并发执行

   1.2 线程

        线程是由进程创建的,是进程的一个实体,一个进程可以拥有多个线程。是进程中的单个顺序控制流,是一条执行路径。就是应用程序中做的事情。比如:360软件中的杀毒,扫描木马,清理垃圾
        单线程
            同一个时刻只允许执行一个线程
        多线程
            同一个时刻,可以执行多个线程
    线程
        用户线程
            也称为工作线程,当线程的任务执行完或以通知的方式结束
        守护线程
            一般是为工作线程服务的,当所有的用户线程结束后,守护线程自动结束,常见的守护线程有  垃圾回收机制
                应用:如果我们希望当main线程结束之后,子线程自动结束,只需要将子线程设置为守护线程即可。设置方法   实例.setDaemon(),位置在实例.start()之前
    注意:一个进程至少包括一个线程

二、并发和并行

  2.1 并行

        在同一时刻,有多个指令在多个CPU上同时执行
        造成一种 貌似同时 的错觉,简单的说,单核cpu实现的多任务就是并行

  2.2  并发

        在同一时刻,有多个指令在多个CPU上交替执行
        多核cpu可以执行并行
    Notes:并发、并行可以同时发生

  2.3 监控线程的执行情况

      在终端输入Jconsole可以监控线程的执行情况

三、创建方式

3.1 继承Thread类



               

         在继承Thread类后,该类就可以当做线程使用。往往要重写run()(Thread实现了Runnable接口),在此方法内写入自己的业务逻辑,运行需要创建该类的实例,通过实例调用start方法。

思考:为什么不直接通过对象调用start()方法?


    当我们运行一个程序时相当于启动了一个线程,当进程启动了以后,在进程开了一个主线程,当main线程执行 实例.start()主线程不会阻塞,会继续执行,如果直接去调用run(),此时的run()就是一个普通的方法,会发生阻塞,没有真正的开启一个线程,只有将run()执行完之后才会去执行其他的语句。真正实现多线程效果的是native 方法 start0()而不是run()。注start0()是由JVM调用,底层是c/c++来实现的(主线程执行完任务就会结束的,但是有子线程在运行时,进程也不会结束的,当所有的线程结束了,进程就结束了)

3.2 实现Runnable接口

    Notes :java是单继承的,在某些情况下一个类可能已经继承了某个父类,这是再用继承Thread类方法来创建线程显然是已经不可能的了。因此Java设计者们提供了另一个方法创建线程,就是通过实现Runnable接口来实现方法
    运行需要新建一个线程,将实现Runnable接口的方法的类的实例放入线程的有参构造的方法,这里是使用设计模式的代理模式 。

3.3 使用Callable创建线程

    和Runnable接口不一样,Callable接口提供了一个call()方法作为线程执行体,call()方法比run()方法功能要强大。

3.4 Callable 和 Runnable的区别

  1.   call()方法可以有返回值
  2.   call()方法可以声明抛出异常 callable接口实现类中的run方法允许异常向上抛出,可以在内部处理,try catch,但是runnable接口实现类中run方法的异常必须在内部处理,不能抛出

        callable和runnable都可以应用于executors。而thread类只支持runnable,

继承Thread和实现Runnable接口两种方法的区别

  1.  从java的设计来看,通过继承Thread或者实现Runnale接口来创建线程本质上没有区   别,Thread本质上也是实现了Runnable接口。
  2.  实现Runnbale接口的方式更加适合多个线程共享一个资源的情况,并且避免了单继承的限制

3.5使用线程池例如Executor框架


    3.5.1  概念

       盛放线程的容器,盛放线程的池子

    3.5.2  好处

       1. 减少频繁创建及销毁线程的操作,节省资源
       2. 线程池会将闲置的线程处理任务,达到线程复用

    3.5.3  线程池执行基本原理

      1.  创建一个池子,此时没有线程    pool.getPoolSize()
      2.   当第一次提交任务给线程池,线程池就会创建线程执行任务。当任务执行完毕。线程对象归还给池子线程并不会消亡
      3.当再次提交任务,此时线程池就会将闲置的线程去处置任务,如果没有闲置的线程,才会创建新的线程

    3.5.4  线程池创建方式

        创建线程池
             ExecutorService pool = Executors.newCachedThreadPool();
             线程池最多创建int最大值个线程
            ExecutorService pool = Executors.newFixedThreadPool(3);
             创建线程池对象,规定最大数
            创建一个线程池,根据需要创建新的线程,但在可用时将重用先前构建的线程
        方式一
           1. 创建一个任务对象
                MyTarget myTarget = new MyTarget();
           2. 提交任务给线程池
                pool.submit(myTarget);
                过去的方式   Thread t1 = new Thread(myTarget);
               缺点:自己创建线程,执行完任务,消亡浪费资源,系统资源开销大
           3. 如果不需要线程池,将其关闭
                pool.shutdown();
        方式二

            匿名内部类

3.5.5 线程池的分类

3.5.6 线程池的核心参数

1. int corePoolSize

      线程池核心线程大小,如果你的任务数量小于核心线程数,那么开启的线程数量还是三个

2.int maximumPoolSize

      线程池最大线程数,基于KeepaliveTime会销毁

3.KeepaliveTime

      空闲线程存活时间

4.TimeUnit 时间单位

      时间单位,为 keepAliveTime 指定时间单位 

5.workQueue  阻塞队列,用于保存任务的阻塞队列

        1). ArrayBlockQueue 基于数组的有界队列,FIFO,防止资源耗尽问题

        2). LinkedBlockQueue基于链表的无界阻塞队列,界值为Integer.MAX FIFO

                        Tips:maximumPoolSize参数是没有用的

        3). SynchronousBlockQueue(不缓存任务队列)

                        Tips:maximumPoolSize参数是有用的,如果超过了会执行拒绝策略

        4). ProprityBlockQueue() 几区Comparator实现,比较 无界阻塞队列

6.ThreadFactory

        创建线程的工程类,例如守护线程daemon

7.RejectedExecutionHandler handler 拒绝策略

        1). callerrunsPolicy(除非线程池shutdown,抛弃任务)

        2). AbortPolicy(直接抛出异常)

        3). DiscardPolicy(什么都不做,直接丢弃任务) //不建议用

        4). DiscardOldestPolicy(什么都不做,直接丢弃队列里面最早的任务)

四、常用方法

用户线程:也叫工作线程,当线程的任务执行完或以通知方式结束

守护线程:一般是为工作线程服务的,当所有的用户线程结束,守护线程自动结束

常见的守护线程:垃圾回收机制

五、多线程实现方案

 六、线程终止

 七、常用方法

八、线程的生命周期

8.1 线程的状态

 8.2 wait()、notify()、notifyAll()类比

九、 线程安全

 9.1 安全问题原因

解决方式

1.同步代码块

2.同步方法

3.Lock锁

9.2  synchronized

1、 Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。

2、每个对象都对应一个可称为互斥锁的标记,这个标记用来保证在任意时刻,只能有一个线程访问该对象。

3. 关键字sychronized来与对象的互斥锁联系,当某个对象用sychronized修饰时,表名该对象在任一时刻只能由一个线程访问。

4.同步的局限性:导致程序的执行效率要降低

5.同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象)

6. 同步方法(静态的)的锁为当前类本身

Java中static作用及用法详解_CrazyCodeBoy的博客-CSDN博客_java static

 被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。

被static关键字修饰的属性或方法不属于实例化的对象,而是属于类,而this属于当前操作的实例对象,所以同步static锁在了类上

public class demoSell{
    //静态方法
    public synchronized static void method1(){

    }
    //静态方法中的同步代码块
    public static void mehtod2(){
        synchronized(demoSell.class){
            
        }
    }
}

注意:

1.同步方法如果没有使用static修饰:默认所对象为this

2.如果方法使用static修饰,默认锁对象:当前类.class

3.实现的落地步骤

       ·需要先分析上锁的代码

       ·选择同步代码块或同步方法

        ·要求多个线程锁对象为同一个即可

1.同步代码块

synchronized(对象){//得到对象的锁,才能操作同步代码块
//需要被同步代码
}

2. sychronized还可以放在方法声明中,表示整个方法为同步方法

public synchronized void method(String name){
//需要被同步的代码
}

9.3 Lock

//创建可重复锁
Lock lock = new ReentrantLock();
//上锁
lock.lock();
//代码块
.............
//释放锁
lock.unlock();

 9.4 线程锁

9.5 并发工具类  ConcurrentHashMap HashMap HashTable

9.6 线程死锁

概念:

多个线程都占用了对方的锁资源,但不肯相让,导致了死锁,在编程一定要避免死锁的发生

9.7 释放锁

1. 当前线程的同步方法,同步代码块执行结束后会自动释放锁

2. 当前线程在同步代码块,同步方法中遇到break、return

3. 当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致异常结束

4. 当前线程在同步代码块、同步方法中执行了线程对象的wait()方法,当前线程暂停并且释放锁

注意:下面的情况不会释放锁

1.线程执行同步代码块或同步方法时,程序调用Thread.sleep()、Thread.yield()方法暂停当前线程的执行,不会释放锁。

2.线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁,应该避免使用suspend()和resume()来控制线程,方法不再推荐使用。

十、思考

1.volatile关键字

在多线程的情况下保证了数据的可见性,加了volatile的属性,一个线程修改后,另一个线程也能看到

原理:一个线程修改了数据,就会把数据刷新到主存中,其他线程读取到的副本就会失效,重新读取主存中的新数据

2.count++ 是不是原子操作

不是,三步操作,:

1.从主存中count的值存到A线成独有的空间

2.在线程独有工作空间中执行+1操作

3.将101重新刷新relaod到主存中

随时可能丢失CPU的执行权,比如在执行+1操作还未刷新到主存,就被其他线程B抢占

3.怎么保证原子操作

1.同步代码块

2.原子类AtomicInteger

4.原子类原理--CAS原理

在修改主存中的值,先拿旧值和主存中的值判断

        如果相等,则直接修改

        如果不等,说明已经有其他线程修改过了,需要重新获取主存中的新值

这里涉及到三个变量

1. 旧值: 第一次获取主存中值时,作为旧值存放在该变量中, 比如100

2. 新值 该线程操作后的值,比如执行++操作后的101

3.要修改的值 主存里面的值

如果旧值和要修改的值相等,说明没有被修改过,可以直接赋值

5.ConcurrentHashMap HashMap 和HashTbale的区别

HashMap效率最高 但是不安全

HashTable 效率最低 安全 每个方法都加锁

ConcurrenetHashp 效率第二高 安全

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java线程、Java多线程详细介绍 的相关文章

  • PAT1003 Emergency (25)

    引论 本以为这是一道水题却因为考虑不周WA了半天 xff0c 参考了博客https blog csdn net tiantangrenjian article details 19434417 感觉这题还是蛮不错的 题目链接 https p
  • 操作系统知识点整理

    1 进程的有哪几种状态 xff0c 状态转换图 xff0c 及导致转换的事件 进程的状态 xff1a 运行 阻塞 就绪三种状态 运行和就绪之间的转换由调度程序引导 xff1b 当进程等待一个外部事件发生时 xff0c 则由执行 阻塞 xff
  • uva417

    挺有意思的一道题 迭代深搜 43 二分 实际上根据笔者测试 xff0c 使用迭代深搜打表后直接用暴力枚举也可以通过 xff0c 但如果测试用例T的范围开到1e5在极端情况下就会TLE xff0c 但是UVA的测试数据显然没有这样的 xff0
  • hiho一下 第216周

    分析 这道题挺不错的 xff0c 巧妙的运用到了优先队列 首先 xff0c 因为n个点是确定的 xff0c 所以我们可以得到n 1个区间 xff1b 其次 xff0c 因为还有k个点是不确定的 xff0c 所以我们把这k个点依次插入到这n
  • Cisco packet tracer模拟器基本配置命令

    引言 计算机网络是门实践性很强的学科 xff0c 如果不自己动手做一些实验的话是根本学不好的 我这里的学好是指真正掌握计算机网络的工作原理以及一些常见的网络设备的使用方法 xff0c 而不是期末考高分或者水过一个什么证书 但是通常情况下我们
  • Wannafly挑战赛24A题

    span class hljs comment 题目链接 xff1a https www nowcoder com acm contest 186 A 分析 xff1a 奇数x分为 xff08 1 xff0c x 1 xff09 时为最优解
  • @ControllerAdvice注解作用及源码解析

    一 概述 在Spring里 xff0c 我们可以使用 64 ControllerAdvice来声明一些全局性的东西 xff0c 其用法主要有以下三点 xff1a 1 64 ExceptionHandler注解标注的方法 xff1a 用于捕获
  • 用Android的Activity生命周期解释HarmonyOS的Page Ability生命周期

    由华为出品 我国完全自主知识产权的HarmonyOS是一款 面向未来 面向全场景 xff08 移动办公 运动健康 社交通信 媒体娱乐等 xff09 的分布式操作系统 现已于2020年9月10日开源 xff0c 并面向应用开发者发布Beta版
  • 宗师级Linux 系统管理员的倾囊相授——《Linux命令行与shell脚本编程大全(第4版)》

    信息安全 早已上升为国家战略 xff0c 发展自主可控的国产操作系统迫在眉睫 为了满足国防 公安等涉密领域对操作系统平台的安全需求 xff0c 国防科技大学研制了以操作系统技术为核心 xff0c 安全可信为特色的中标麒麟 xff08 Ubu
  • Java语言的极限,就是面向对象的极限——《On Java中文版》

    自从1995年问世以来 xff0c Java已经发展成了全世界使用范围最广的语言之一 xff0c 每天都有30亿台运行Java的设备活跃在这个世界上的各个角落里 世界上大多数网站的后台使用Spring开发 xff0c 而Spring开发者必
  • 做后台开发用到的技能都在这儿——《后台开发:核心技术与应用实践》

    大多数面向对象语言没有指针的概念 xff0c C语言也没有对象的概念 xff0c 同时具有指针和对象的 C 43 43 语言在学习时有高昂的门槛 xff0c 同时在服务端后台开发 处理多并发的海量网络请求等方面有天然的优势 就像 Andro
  • Android Canvas 多张图片拼接成长图

    容我慢写
  • matplotlib里的动画

    本文由Mathematrix译自由Jake Vanderplas撰写的Matplotlib Animation Tutorial Matplotlib 1 1 版新添加了一些非常帅的用来制作动画的工具 xff0c 你可以在Matplotli
  • Android Canvas 给图片加上水印

    容我慢写
  • 我做面试官的故事

    2016年就要过完了 xff0c 我入行也快三年了 三年来被人面试过也面试过人 xff0c 我来给大家分享一下我面试别人的两个有趣经历吧 xff1a 1 有一天我穿着环信的T恤 xff0c 前胸是一个巨大的环信logo xff0c 后颈是环
  • 给CheckBox加上动画

    容我慢写
  • Android程序员的十大转型之路

    IT行业是一个瞬息万变的行业 xff0c 程序员是一个不进则退的职业 我作为一个Android程序员 xff0c 多年来一直保持随时可以转型其他技术领域的状态 xff0c 保持对新技术敏感的嗅觉 我先说说Android程序员不可能转型的几个
  • 【玖哥乱弹】编程语言间的斗争

    在初级程序员阶段 xff0c 每个人都不可避免遇到选择编程语言和职业方向的难题 我挑选了几个常见的编程语言 xff0c 分析了优缺点和职业方向 xff0c 以供想当程序员的人参考 C C 43 43 一句话概括 xff1a 大多数中国程序员
  • 【玖哥乱弹】成功的IT人士这样转型AI

    AlphaGo在与围棋世界冠军的对弈大获全胜 xff0c 不但让我们领略到了AI的巨大潜力 xff0c 还把AI推上了新的浪潮之巅 作为一个从即将过去的移动互联网时代走来的Android工程师 xff0c 我深深感受到自己成了传统行业 xf
  • 【玖哥乱弹】程序员如何成为别人的男朋友

    这个世界上程序员数量很多 xff0c 有女朋友的程序员在其中的比例却很少 究其原因 xff0c 不外乎大多数程序员根本不知道怎么才能成为别人的男朋友 成为别人的男朋友对于富二代和拆迁户很容易 xff0c 而对于程序员却很难 xff0c 潘驴

随机推荐

  • wm命令使用方法(修改android 分辨率)修改

    注 xff1a Android 4 3引入的wm工具 wm命令及用法 xff1a 系统说明 xff1a usage wm subcommand options wm size reset WxH wm density reset DENSI
  • 给单个项目单独设置git账号

    一 直接复制带有git账号的项目 直接复制整体项目 其中里面带有 git文件 二 其他方案 暂时没查出来
  • 互联网 Java 工程师面试题之Spring(二)

    Spring 面试题 xff08 二 xff09 1 什么是 spring Spring 是个 java 企业级应用的开源开发框架 Spring 主要用来开发 Java 应用 xff0c 但是有些扩展是针对构建 J2EE 平台的 web 应
  • (IDEA2020 在使用maven时遇到servlet依赖包错误,Error:(6, 37) java: 程序包org.apache.ibatis.annotations不存在)

    IDEA2020 在使用maven时遇到servlet依赖包错误 xff0c Error 6 37 java 程序包org apache ibatis annotations不存在 一 错误显示 xff0c 在本地仓库有依赖的情况下 xff
  • Spring Security(十一) Spring Security 中 CSRF

    从刚开始学习 Spring Security 时 xff0c 在配置类中一直存在这样一行代码 xff1a http csrf disable 如果没有这行代码导致用户无法被认证 这行代码的含义是 xff1a 关闭 csrf 防护 1 什么是
  • 谈谈我对多线程的理解

    一 提到多线程 xff0c 就不得不理解以下几点 xff1a 1 程序 xff0c 进程 xff0c 线程这三者之间的关系 xff1f 简单来说 xff0c 一程序可以调用多个进程 xff0c 比如一个视频播放器程序 xff0c 里面就存在
  • 消费者行为分析包含了哪些内容?

    消费者市场 指个人或家庭为满足生活需求而购买或租用商品的市场 消费者市场特点 1 购买者众多 xff0c 购买数量零星 xff0c 对日用品的消费需要经常性购买 xff0c 购买频率高且量小 xff0c 支付的金额数也小 2 需求差异性大
  • 一个快速从中文文本抽取关键短语的工具 ckpe 提取关键短语

    一个从 中文自然语言文本 中抽取 关键短语 的工具 需要调用的话 xff0c 请直接进入github查看调用方法 xff1a 源码地址 xff1a ckpe 戳这里 61 gt 在线直接试用 关键短语抽取在线版 应用场景 Applicati
  • kali 下libnl-3-dev : 依赖: libnl-3-200 (= 3.2.24-2) 但是 3.2.27-2 正要被安装

    1 先说问题 sudo apt get install libnl span class hljs number 3 span dev 正在读取软件包列表 span class hljs keyword span 完成 正在分析软件包的依赖
  • android的system域解耦

    google很早在为此做准备 xff0c 要求所有设备能够刷GSI xff08 通用系统镜像 xff09 xff0c 并跑过XTS测试 动态分区解耦方案如上图 一 分区描述 单一系统映像 SSI 包含system和system ext图像的
  • Android Activity onConfigurationChanged()方法 监听状态改变

    AndroidManifest xml文件 xff1a 1 增加权限android permission CHANGE CONFIGURATION 2 设置Activity的android configChanges属性 span clas
  • 生产者消费者

    问题意义 生产者消费者问题是一个很经典的问题 xff0c 通过解决此问题 xff0c 能够学到多线程的的知识 程序设计思路 在本程序中采用信号灯的方式 xff0c 用Flag作为标志位 xff0c 指示生产过程和消费过程是否结束 Flag为
  • android keymaster

    keymaster span class hljs keyword is span a newly instroduced key management hardware abstraction layer hal component It
  • Android密钥证书管理相关介绍

    Java Security Java Security是Java中的安全模块 xff0c 它对应了一系列的规范 xff0c 主要包含三个重要规范 xff1a JavaCryptography Extension xff08 简写为JCE x
  • 安装依赖包 -- Ubuntu

    安装依赖包 xff08 须在虚拟环境中 xff09 xff1a 依赖就是开发以及程序运行需要使用的环境的集合 包括软件 插件等 我们一般会把需要使用的依赖给保存在一个文件中 xff0c 命名为requirements的txt文件 如果在其它
  • 大数据的感想

    1 大数据即全数据 xff08 即n 61 All xff0c 这里n为数据的大小 xff09 xff0c 其旨在收集和分析与某事物相关的 全部 数据 xff0c 而非仅分析 部分 数据 2 N 61 All xff08 所有 xff09
  • 新手如何配置spring

    首先 xff0c 可以通过springframework官方说明文档找到如下网址下载spring包 http repo spring io release org springframework spring 这里以4 2为例子 sprin
  • 对Zookeeper的分布式锁的浅解

    提起到锁 xff0c 我们在单机应用开发涉及到同步问题时往往会采用Sychronized Lock的方式进行解决多线程的代码同步问题 xff0c 此时多线程的运行都是在同一个JVM中 但是在分布式集群的情况下 xff0c 此时多线程的运行在
  • com.github.tobato.fastdfs.exception.FdfsServerException: 错误码:2,错误信息:找不到节点或文件

    我的原因是因为docker中Tracker没有启动起来 xff0c 重新启动后系统正常
  • Java线程、Java多线程详细介绍

    目录 一 进程和线程的区别 1 1 进程 1 2 线程 二 并发和并行 2 1 并行 2 2 并发 2 3 监控线程的执行情况 三 创建方式 3 1 继承Thread类 思考 xff1a 为什么不直接通过对象调用start xff08 xf