JUC并发编程基础(包含线程概念,状态等具体实现)

news2025/2/24 6:29:56

一.JUC并发编程基础

1. 并行与并发

1.1 并发:

  1. 是在同一实体上的多个事件
  2. 是在一台处理器上"同时处理多个任务"
  3. 同一时刻,其实是只有一个事件在发生.

即多个线程抢占同一个资源.
在这里插入图片描述

1.2 并行

  1. 是在不同实体上的多个事件
  2. 是在多台处理器上同时处理多个任务
  3. 同一时刻,大家都在做事情.你做你的,我做我的.

即多个线程同时执行.

在这里插入图片描述

2. 进程,线程,管程

2.1 进程

在系统中运行的一个应用程序就是一个进程,每一个进程都有它自己的内存空间和系统资源.

2.2 线程

也被叫做轻量级进程,在同一个进程内会有1个或多个线程,是大多数操作系统进行时序调度的基本单元

2.3 管程

也被称为Monitor(监视器),也就是平时我们所说的锁.

3. 线程启动的三种方式

3.1 继承Thread类.重写run方法

继承重写

    public class MyThread extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + " " + i);
            }
        }
    }

执行

    public class ExtendThreadMain {
        public static void main(String[] args) {
            MyThread myThread = new MyThread();
            myThread.start();
        }
    }

注意:启动线程是调用父类的start方法,而不是直接去调用run方法.

3.2 实现Runable接口

实现重写

    public class MyThread implements Runnable{
        @Override
        public void run() {
            for(int i=0;i<10;i++){
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
    

主函数启动线程

    public class RunnableThreadMain {
        public static void main(String[] args) {
            MyThread myThread = new MyThread();
    
            Thread t1 = new Thread(myThread);
    
            t1.start();
        }
    }
    

当然我们还有另外一种写法

注意到Thread的构造方法的参数有
在这里插入图片描述

里面存在一个Runnable参数和一个线程名的两个参数的方法.熟悉静态内部类或者Lamba表达式的应该了解,这里完全可以利用这种特性来启动线程,所以我们可以这样改写.


    public class RunnableThreadMain {
        public static void main(String[] args) {
    //        MyThread myThread = new MyThread();
    //        Thread t1 = new Thread(myThread);
    
            Thread t1 = new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    System.out.println(Thread.currentThread().getName() + " " + i);
                }
            }, "t1");
    
            t1.start();
        }
    }
    

3.3 实现Callable接口

实现重写call方法(其实也就跟上述两个的run方法的作用一样)

    /**
     * 这里的泛型指的是call方法的返回值
     */
    public class MyThread implements Callable<Integer> {
    
        @Override
        public Integer call() throws Exception {
            int sum = 0;
            for (int i = 0; i < 100; i++) {
                sum+=i;
            }
            return sum;
        }
    }

主函数调度,这里与其他两种实现不同的是,可以有返回值,这里引用了FutureTask接口来接收这个值

    public class CallableThreadMain {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
    
            MyThread myThread = new MyThread();
    
            FutureTask<Integer> futureTask = new FutureTask<>(myThread);
    
            Thread t1 = new Thread(futureTask);
    
            t1.start();
    
            Integer sum = futureTask.get();
            System.out.println("sum = " + sum);
        }
    }
    

注意:get方法时,方法会阻塞,直到这个线程执行完毕有返回值,代码才会往下进行.

4. 守护线程

守护线程

  • 守护线程是一种特殊的线程,它并不属于用户线程,也不受用户线程的控制,但它却有着特殊的重要性。
  • 守护线程的主要目的是为其他非守护线程提供服务。当所有的用户线程都结束时,守护线程也会随之结束
  • 守护线程的创建方式是在启动线程时调用Thread.setDaemon(true)方法,该方法将线程设置为守护线程。
  • 判断当前线程是否为守护线程调用 Thread.currentThread().isDaemon()方法,true为是,false为不是

守护线程的退出条件是:

  1. 所有用户线程都结束;
  2. 调用了Thread.stop()方法;
  3. 调用了Runtime.exit()方法。

注意:

  1. 守护线程只能有一个,一个JVM中只能有一个守护线程;
  2. 守护线程不能执行用户线程的run()方法,因为它没有用户线程可执行;
  3. 守护线程的优先级比较低,它只会在JVM中运行,不会影响到其他线程的运行;
  4. 守护线程的异常处理方式和非守护线程相同。
    public class ProtectThread {
        public static void main(String[] args) {
            //创建一个线程
            Thread t1 = new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + ": " +
                        (Thread.currentThread().isDaemon() ? " 守护线程" : "用户线程"));
                while (true) {
                }
            },"t1");
            t1.setDaemon(true);//设置为守护线程
            t1.start();
            
            System.out.println(Thread.currentThread().getName() + ": " +
                    (Thread.currentThread().isDaemon() ? " 守护线程" : "主线程"));
        }
    }

5. windows,linux下查看和杀死进程

5.1windows

  • 任务管理器可以查看进程和线程数,也可以用来杀死进程.

  • tasklist 查看进程
    在这里插入图片描述

  • taskkill 杀死进程

    • 通常带两个参数 /F 强制杀死 /PID 进程id

5.2 linux

  • ps -ef 查看所有进程
    在这里插入图片描述

  • ps -fT -p 查看某个进程(PID)的所有线程

在这里插入图片描述

  • kill 杀死进程
  • top按大写H切换是否显示线程

动态展示所有进程占用cpu的情况
在这里插入图片描述

  • top -H -p 查看某个进程(PID)的所有线程

5.3 查看Java的进程

  • jps 命令查看所有 Java进程

  • jstack 查看某个Java进程 (PID) 的所有线程状态.
    在这里插入图片描述

  • jconsole 来查看某个Java进程中线程的运行情况(图形界面)
    在这里插入图片描述

6. 线程运行原理

我们知道JVM虚拟机中有栈和堆两块内存区域.

而每一个线程都有属于自己的栈区,每个线程直接的栈互不干扰,线程中每一个方法都是一个栈帧.

看如下这段代码的调度过程:
在这里插入图片描述

我们再通过一幅图来理解

在这里插入图片描述

7. 线程的上下文切换

有些时候由于一些原因,当线程在执行时,cpu被其他线程抢占到也就是说存在线程之间的切换的过程,我们称为上下文切换.

哪些原因会导致线程上下文切换呢

  • 线程的cpu时间片用完
  • 垃圾回收
  • 有更高优先级的线程需要运行
  • 线程自己调用了sleep,yield,wait,join,park,synchronized,lock等方法

当上下文切换时,需要由操作系统去保存当前线程的状态,也就是记录其中的一些变量啊,执行到哪一步啦,并恢复另一个线程的状态,Java中对应的概念就是程序计数器,它的作用是记住下一条JVM指令的执行地址,是线程自己私有的

  • 状态包括程序计数器,虚拟机栈中每个栈帧的信息,如局部变量,操作数栈,返回地址

注意:频繁的上下文切换会影响性能.

8. 线程的几种状态

8.1 五种(来源于操作系统)

在这里插入图片描述

  • 初始状态: 相当于我们刚刚new出来一个线程对象.仅是在语言层面创建了线程对象,还并未与操作系统线程相关联.
  • 可运行状态(就绪状态) : 指该线程已经被创建(与操作系统线程关联),可以由CPU调度执行.也就是都准备去抢占cpu啦,如果抢到了就会进入运行状态
  • 运行状态: 指获取了CPU时间片运行中的状态.
    • 当CPU时间片用完会从运行状态转换至就绪状态, 会导致线程的上下文切换
  • 阻塞状态
    • 如果调用了阻塞的API,例如BIO(同步阻塞IO)读写文件,这时该线程不会用到CPU,会导致线程上下文切换,进入阻塞状态.
    • 等BIO操作完毕,会由操作系统唤醒阻塞的线程,转换至可运行状态.
    • 与可运行状态的区别是,对阻塞状态的线程来说只要它们一直不唤醒,调度器一直不会考虑调度它们.

可以这样理解: 好比去上厕所,你抢到厕所的使用权啦,但是突然你又不想上啦,想起还有其他事情要做,总不能占着茅坑不拉屎叭,所以cpu,也就是厕所,你得离开这里,这个时候你去干其他的事都可以,等你忙完又想上厕所啦,这个时候又和别人一样需要有机会才能抢到厕所的使用权,也就是重新回到就绪状态.

  • 终止状态: 表示线程已经执行完毕,生命周期已经结束,不会在转换为其他状态.也就是代码执行完毕,没有循环的包裹,执行完就会进入终止状态.

8.2 六种(Java层面)

我们来查看Thread类当中的一个枚举类State
在这里插入图片描述
所以一共有六种状态,其具体为
在这里插入图片描述

  • NEW 线程刚被创建,但是还没有调用start()方法
  • RUNNABLE当调用了start()方法之后.

注意: JavaAPI层面的RUNNABLE状态涵盖了操作系统层面的可运行状态(就绪状态),运行状态,阻塞状态(由于BIO导致的线程阻塞,在Java里无法区别,仍然认为是可运行,也就是RUNNABLEZ状态)

  • BLOCKED 可以理解为抢占锁时未抢到,造成阻塞等待
  • WAITING 等待别的线程执行结束
  • TIMED_WATING 有时间的等待,也就是对应Thread.sleep();
  • TERMINATED 当线程代码运行结束
8.2.1 代码实现每种状态
  • NEW (创建线程不开始)
    在这里插入图片描述

  • RUNNABLE(就绪,运行,阻塞(操作系统的层面例如IO流时))
    在这里插入图片描述

  • TERMINATED (代码执行完毕就进入此状态)
    在这里插入图片描述

  • TIMED_WATING (睡眠时进入)
    在这里插入图片描述

  • WAITING(利用join方法,使线程2等待线程1执行完毕,此时状态为WAITING)
    在这里插入图片描述

  • BLOCKED(阻塞,抢占锁失败,阻塞等待)
    在这里插入图片描述

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

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

相关文章

智慧交通运行监测与应急指挥中心方案

建设目标 建立感知层数据的实时采集以及数据处理&#xff0c;实现监测预警自动化和智能化&#xff1b;推动交通运输数据资源开放共享&#xff0c;打破数据资源壁垒&#xff0c;与城市各部门数据建立共享交换机制&#xff0c;实现应急指挥的协同化&#xff1b;充分运用大数据、互…

适合家居建材企业的CRM系统盘点(2024版)

当前&#xff0c;CRM市场上&#xff0c;国际巨头的市场优势正在逐渐减弱&#xff0c;国内CRM企业奋起追赶&#xff0c;呈现出强劲的崛起势头。因此&#xff0c;对于家居建材企业来讲&#xff0c;在进行CRM选型时&#xff0c;如何选择一款合适的系统是关乎企业高效发展的重要课题…

(6)qml 画布元素(Canvas Element)

基本思想 画布元素&#xff08;canvas element&#xff09;的基本思想是使⽤⼀个2D对象来渲染路径。这个2D对象包括了必要的绘图函数&#xff0c;画布元素&#xff08;canvas element&#xff09;充当绘制画布。2D对象⽀持画笔&#xff0c;填充&#xff0c;渐变&#xff0c;⽂…

小型气象站在现代农业中的应用与前景

随着科技的飞速发展&#xff0c;智慧农业已成为现代农业发展的重要趋势。在这一背景下&#xff0c;小型气象站作为智慧农业的重要组成部分&#xff0c;正逐渐展现出其独特的价值和广阔的应用前景。本文将从小型气象站的定义、功能、应用案例以及未来展望等方面&#xff0c;探讨…

文化创新与社交媒体:探索Facebook的足迹

在过去的十多年里&#xff0c;Facebook从一个简单的校园社交网络发展成为全球最大的社交媒体平台之一。它不仅改变了人们的沟通方式&#xff0c;更在许多方面推动了文化的创新和变革。本文将深入探索Facebook如何通过其平台的演进和功能创新&#xff0c;成为文化创新的重要推动…

合合信息大模型“加速器”亮相2024世界人工智能大会,助力大模型学好“专业课”

7月4日至7日&#xff0c;2024世界人工智能大会在上海拉开帷幕。现阶段&#xff0c;“百模大战”现象背后的中国大模型发展前景与堵点仍然是各界关注的焦点。如何帮助大模型在信息的海洋中快速找准航向&#xff0c;在数据的荒漠中找到高质量的“水源”&#xff1f;合合信息在本次…

Netty学习(NIO基础)

NIO基础 三大组件 Channel and Buffer 常用的只有ByteBuffer Selector&#xff08;选择器&#xff09; 结合服务器的设计演化来理解Selector 多线程版设计 最早在nio设计出现前服务端程序的设计是多线程版设计,即一个客户端对应一个socket连接,一个连接用一个线程处理,每…

雷电模拟器报错remount of the / superblock failed: Permission denied remount failed

报错截图 解决方法 打开设置 设置配置system.vmdk可写入 解决

前端从业者的历史难题Vue和React的抉择:难度不亚于丈母娘和媳妇

**前端从业者的历史难题&#xff1a;Vue和React的抉择——难度不亚于丈母娘和媳妇** Vue和React这两个框架无疑是当下最为流行的两个选择。它们各自拥有独特的优势和特点&#xff0c;吸引了大量的前端从业者。然而&#xff0c;对于许多从业者来说&#xff0c;如何在Vue和React…

基于大数据+Hadoop的豆瓣电子图书推荐系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行交流合作✌ 主要内容&#xff1a;SpringBoot、Vue、SSM、HLM…

Automotive之CarService和Vehicle

目录 前言一、CarService1.1 CarService 组成1.2 编译产物1.3 CarService的使用1.3.1 第一步&#xff1a;判断是否支持车载功能1.3.2 创建Car&#xff0c;获取 Manager 1.4 CarService实现原理1.4.1 启动CarServiceHelperService服务1.4.2 绑定 CarService 服务1.4.3 CarServic…

swagger的接口文档导入到yapi上

一、访问swagger接口 swagger集成到项目后&#xff0c;通过http:\\ip:port/swagger-ui.html 访问。 说明&#xff1a;这里的路径是基于swagger2。如果用swagger3&#xff0c;需要用swagger3的路径进行访问。 访问如图&#xff1a; 这就是swagger接口首页。如果想导入到yapi上…

PD虚拟机怎么联网?PD虚拟机安装Win11无法上网 pd虚拟机连不上网怎么解决 mac安装windows虚拟机教程

PD虚拟机既可以联网使用&#xff0c;也可以单机使用。如需将PD虚拟机联网&#xff0c;可以共享Mac原生系统的网络&#xff0c;其使用体验与真实系统无异。本文会详细讲解PD虚拟机如何联网&#xff0c;并会进一步解决PD虚拟机安装Win10无法上网的问题。 如果有网络相关问题的小伙…

SQL 与 NoSQL 数据库:一场关于灵活性与结构的对话

文章目录 引言SQL 数据库&#xff1a;传统之光定义特征优势缺点 NoSQL 数据库&#xff1a;新时代的弹性定义特征优势缺点 何时选择 NoSQL&#xff1f;场景1&#xff1a;海量数据与高并发场景2&#xff1a;灵活性需求场景3&#xff1a;实时数据分析场景4&#xff1a;分布式系统 …

无人机水运应用场景

航行运输 通航管理&#xff08;海事通航管理处&#xff09; 配员核查流程 海事员通过VHF&#xff08;甚高频&#xff09;系统与船长沟通核查时间。 无人机根据AIS&#xff08;船舶自动识别系统&#xff09;报告的船舶位置&#xff0c;利用打点定位 功能飞抵船舶上方。 使用…

TikTok马来西亚直播网络怎么配置?

TikTok是一款全球流行的社交媒体应用&#xff0c;在东南亚地区拥有大量用户。在马来西亚这个多元化的国家&#xff0c;配置高效稳定的直播网络对TikTok的运营至关重要。 配置马来西亚直播网络的必要性 广泛的地理覆盖&#xff1a;马来西亚包括大片陆地和众多岛屿&#xff0c;网…

求 自然对数 ln(x)

np.log()函数是用来计算数组中每个元素的自然对数的。自然对数是以数学常数e&#xff08;约等于2.71828&#xff09;为底的对数。NumPy作为一个强大的数值计算库&#xff0c;提供了很多用于数组操作的函数&#xff0c;np.log()就是其中之一。 • 下面是一个简单的例子&#xff…

某某市信息科技学业水平测试软件打开加载失败逆向分析(笔记)

引言&#xff1a;笔者在工作过程中&#xff0c;用户上报某某市信息科技学业水平测试软件在云电脑上打开初始化的情况下出现了加载和绑定机器失败的问题。一般情况下&#xff0c;在实体机上用户进行登录后&#xff0c;用户的账号信息跟主机的机器码进行绑定然后保存到配置文件&a…

RNN文献综述

循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;是一种专门用于处理序列数据的神经网络模型。它在自然语言处理、语音识别、时间序列预测等领域有着广泛的应用。本文将从RNN的历史发展、基本原理、应用场景以及最新研究进展等方面进行综述。 历…

阿里云RDS云数据库库表恢复操作

最近数据库中数据被人误删了,记录一下恢复操作方便以后发生时进行恢复. 1.打开控制台&#xff0c;进入云数据库实例. 2.进入实例后 &#xff0c;点击右侧的备份恢复&#xff0c;然后看一下备份时间点&#xff0c;中间这边都是阿里云自动备份的备份集&#xff0c;基本都是7天一备…