40、Java 并发编程基础 ①

news2024/11/25 7:06:24

目录

  • 一、进程(Process)
  • 二、线程(Thread)
  • 三、线程的串行
  • 四、多线程
  • 五、多线程原理
  • 六、多线程优缺点
  • 七、Java 的默认线程
  • 八、开启新线程
    • (1) new Thread()
    • (2) 继承 Thread,重写 run 方法
    • (3) run() 和 start()
  • 九、多线程的内存布局
  • 十、线程的六种状态
  • 十一、sleep、interrupt

一、进程(Process)

  • 进程:操作系统中运行的应用程序

在这里插入图片描述

  • 进程与进程之间是独立的
  • 每个进程都运行在其专用且受保护的内存空间中
    在这里插入图片描述

二、线程(Thread)

  • 一个进程要想执行任务就必须要有线程(一个进程至少要有一个线程
  • 一个进程中的所有任务都在线程中执行

在这里插入图片描述

三、线程的串行

  • 线程中任务的执行是串行
  • 若要在一个线程中执行多个任务,那么只能一个一个地按顺序地执行这些任务
  • 同一时间内,一个线程只能执行一个任务

在这里插入图片描述

四、多线程

  • 一个进程中可以开启多个线程、所有线程并行(同时)执行不同的任务
  • 进程 👉 车间;线程 👉 车间工人
  • 多线程技术可以提高程序的执行效率

在这里插入图片描述

五、多线程原理

  • 同一时间,CPU 的一个核心只能处理一个线程(只有一个线程在工作)
  • 多线程并发(同时)执行,其实是 CPU 快速地在多个线程之间调度(切换)

在这里插入图片描述

  • 如果 CPU 调度线程的速度足够快,就造成了多条线程并发执行的假象

  • 如果是多核 CPU,才是真正地实现了多个线程同时执行

  • 若线程非常多:① CPU 将在多个线程之间来回调度,效率大量 CPU 资源;② 每条线程被调度执行地频次会降低(线程的执行效率会降低)

六、多线程优缺点

  • 优点:① 能适当提高线程的执行效率;② 能适当提高资源利用率(CPU、内存利用率)
  • 缺点:① 开启线程会占用一定的内存空间。若开启大量线程,会占用大量的内存空间,降低程序性能;② 线程越多,CPU 在调用线程上的开销越大

七、Java 的默认线程

  • 每个 Java 程序启动后会默认开启一个线程,称为主线程(main 方法所在线程)

  • 每一条线程都是一个 java.lang.Thread 对象,可通过 Thread.currentThread 方法获取当前线程的线程(Thread) 对象

在这里插入图片描述

在这里插入图片描述

八、开启新线程

(1) new Thread()

public class QQTest {

    public static void main(String[] args) {
        // ① 创建了线程对象 musicThread
        Thread musicThread = new Thread(new Runnable() {
            @Override
            public void run() {
                // 这条线程中要执行的任务
                System.out.println("\n播放音乐");
                System.out.println(Thread.currentThread());
            }
        });

        musicThread.setName("Thread-music");
        musicThread.setPriority(10);

        // ② 开启 musicThread 线程
        musicThread.start();
    }

}

在这里插入图片描述
在这里插入图片描述

(2) 继承 Thread,重写 run 方法

public class QQTest {
    public static void main(String[] args) {
        MusicThread musicThread = new MusicThread();
        musicThread.setName("Music-Thread");

        musicThread.start();
    }
}

class MusicThread extends Thread {
    @Override
    public void run() {
        // 该线程要执行的任务
        System.out.println(getName() + "_播放音乐");
    }
}

在这里插入图片描述

(3) run() 和 start()

public class QQTest {
    public static void main(String[] args) {
        Thread newThread = new Thread(() -> {
            System.out.println(Thread.currentThread());
        });

        // Thread[Thread-0,5,main]
        newThread.start();

        // Thread[main,5,main]
        newThread.run();
    }
}

九、多线程的内存布局

PC 寄存器(Program Counter Register):每个线程都有自己的 PC 寄存器。
PC 寄存器记录着 JVM 正在执行哪一条语句

Java 虚拟机栈(Java Virtual Machine Stack):每个线程都有自己的 Java 虚拟机栈

(Heap):多个线程共享堆空间

方法区(Method Area):多个线程共享方法区
方法区放代码

本地方法栈(Native Method Stack):每个线程都有自己的本地方法栈

十、线程的六种状态

  • 可通过 Thread 对象的 getState() 获得线程的状态

① NEW(新建):尚未启动
在这里插入图片描述

② RUNNABLE(可运行状态):正在 JVM 中运行【或正在等待操作系统的其他资源(如:处理器)】
在这里插入图片描述

③ BLOCKED(阻塞状态):正在等待监视器锁(内部锁)
在这里插入图片描述

④ WAITING(等待状态):在等待另一个线程
调用以下方法会进入 WAITING 状态:
✏️ 没有超时值的:Object.wait
✏️ 没有超时值的:Thread.join
✏️ LockSupport.park

⑤ TIMED_WAITING(定时等待状态)
调用以下方法会进入 TIMED_WAITING状态:
✏️ Thread.sleep
✏️ 有超时值的:Object.wait
✏️ 有超时值的:Thread.join
✏️ LockSupport.parkNanos
✏️ LockSupport.parkUntil

⑥ TERMINATED(终止状态):已经执行完毕

public class QQTest {
    public static void main(String[] args) {
        // 主线程对象
        Thread mainThread = Thread.currentThread();
        // RUNNABLE
        System.out.println(mainThread.getState().name());

        // 子线程
        Thread subThread = new Thread();
        // NEW
        System.out.println(subThread.getState().name());
    }
}

在这里插入图片描述

十一、sleep、interrupt

  • 可通过 Thread.sleep 方法暂停(睡眠)当前线程,进入 WAITING 状态

  • 在暂停(睡眠)期间,若调用线程对象的 interrupt 方法中断线程,会抛出 java.lang.InterruptedException

public class QQTest {
    public static void main(String[] args) {

        Thread subThread = new Thread(() -> {
            System.out.println("666");
            try {
                Thread.sleep(3333);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("520");
        });

        subThread.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("111");
        subThread.interrupt();
    }
}

在这里插入图片描述

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

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

相关文章

AutoCV第八课:3D基础

目录 3D基础前言1. nuScenes数据集2. nuScenes数据格式3. 点云可视化总结 3D基础 前言 手写 AI 推出的全新保姆级从零手写自动驾驶 CV 课程,链接。记录下个人学习笔记,仅供自己参考。 本次课程主要学习点云数据的可视化。 课程大纲可看下面的思维导图。…

【Shiro】SimpleAuthenticationInfo如何验证password

一、前言 通篇的关键就是知道ShiroRealm类重写的doGetAuthenticationInfo这个方法,到底是谁的方法。 从上图我们可以知道,ShiroRealm最终继承到了AuthenticatingRealm这个方法。 二、自定义的ShiroRealm类 ps:该图中①上的注释是没看过底…

Jetpack之livedata原理

1.LiveData是什么? 只有在生命周期处于started和resumed时。livedata才会更新观察者 2.Livedata的各种使用方式 1.更新数据 class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceSta…

c++之函数对象和谓词

目录 函数对象: 谓词: 一元谓词函数举例如下 二元谓词举例如下 函数对象和函数的区别 一元谓词的案例 二元函数对象案例 二元谓词案例 函数对象: 重载函数调用操作符的类,其对象常称为函数对象(function obj…

内网渗透之linux到linux横向移动-ssh

0x01 一般情况下SSH密钥存放在~/.ssh/目录下,也可以文件中搜索已保存的SSH凭证 ~/.ssh/config ~/.ssh/known_hosts ~/.bash_history grep -ir "BEGIN RSA PRIVATE KEY" /* grep -ir "BEGIN DSA PRIVATE KEY" /* grep -ir "BEGIN OPENSSH…

SpringBoot入门学习笔记-快速认识

SpringBoot入门学习笔记-快速认识 快速案例入门案例解析parentstarter引导类内嵌tomcat ) 快速案例 在controller定义一个类 package com.ustc.sp5.controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.…

redis 数据类型简介

redis 数据类型 redis的五种数据类型是:1、string(字符串);2、hash(哈希);3、list(列表);4、set(集合);5、sort set &…

QT初体验:手把手带你写一个自己的串口助手

前言 本文记录一下用QT Creator 写一个基本功能齐全的串口助手的过程,整个工程只有几百行代码,跟着做下来对新手来说可以更快了解整个QT项目的开发过程和一些常用控件的使用方法。对新手学习QT能增强信心,话不多说,正文开始 先看…

Mysql日志redo log、bin log、undo log 区别与作用及二阶段提交

一、redo log 重做日志 作用:确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。 内容:物理格式的日志&#x…

46-Dockerfile-USER/WORKDIR指令

USER/WORKDIR指令 前言USER作用格式使用示例 WORKDIR作用格式说明使用示例 前言 本篇来学习下Dockerfile中的USER/WORKDIR指令 USER 作用 指定运行容器时的用户名或 UID,后续的RUN等指令也会使用指定的用户身份 说明: USER 只是帮助我们切换到指定的…

12_Uboot启动流程_4

目录 images全局变量 do_bootz函数 bootz_start函数 do_bootm_states函数 bootm_os_get_boot_func函数 do_bootm_linux函数 images全局变量 不管是bootz还是bootm命令,在启动Linux内核的时候都会用到一个重要的全局变量:images, images在文件cmd/bootm.c中有如下定义: i…

【2023/05/09】Scratch

Hello!大家好,我是霜淮子,2023倒计时第4天。 Share The mighty desert is burning for the love of a blade of grass who shaks her head and laughs and flies away. 译文: 无垠的沙漠热烈追求一叶绿草的爱,她摇摇…

PCL中点云分割算法简析

文章目录 前言一、点云分割算法简介1.1 基于RANSAC的点云分割1.2 基于聚类的点云分割1.2.1 欧式聚类分割 1.3 基于深度学习的点云分割 二、算法示例2.1 基于RANSAC的平面分割2.2 欧式聚类2.3 基于PointNet的点云分割 总结 前言 点云分割算法广泛应用于激光遥感、无人驾驶、工业…

centos安装nginx教程

安装所需环境 Nginx 是 C语言 开发,建议在 Linux 上运行,当然,也可以安装 Windows 版本,本篇则使用 CentOS 7 作为安装环境。 一. gcc 安装 安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境&#xff0c…

【ESD专题】案例:TVS管钳位电压能不能通过TLP测试数据表征?

这几天遇到一个问题,就是还是想说TVS管导入的时候需要进行IEC61000-4-2 8kV接触静电的钳位波形测试。 比如有时可以看到规格书中给出对应的在IEC61000-4-2 8kV接触时的真实钳位波形: 根据我们文章【ESD专题】TVS管的选择的误区及钳位电压测试方法和一些参考手册所说…

计算机操作系统第四版第七章文件管理—课后习题答案

1.何谓数据项、记录和文件? 数据项:是最低级的数据组织形式,可以分为两种类型:基本数据项和组合数据项。基本数据项是用于描述一个对象的某种属性的字符集,是数据组织中可以命名的最小逻辑数据单位,又称为字…

使用volta对node版本进行控制

安装volta 首先下载volta 下载完成之后在电脑上使用命令行工具查看是否安装成功 volta -v 使用 volta -h 命令可以查看volta的一些用法 安装全局的node版本,可以有三种,第一种是安装最新的,第二种是安装某一个大版本下的,第三种是安装指定的node版本(安装的时候需要等待一段时…

Rest风格复习

Rest风格复习 简介三种注解的风格快速开发 简介 通过一段路径和访问方式来确定访问资源的行为方式 使用POST方式 // value定义 路径 method定义访问的方式RequestMapping(value "/users",method RequestMethod.POST)ResponseBodypublic String save(){System.out.…

Andrew Ng和OpenAI教你写prompt

课程地址: https://learn.deeplearning.ai/chatgpt-prompt-engb站搬运: https://www.bilibili.com/video/BV1No4y1t7Zn 教学人员:Lsa Fulford, Andrew NG LLM的两种样式 Base LLM:基于文本训练数据预测下一个词的概率&#xff0…

制作Alpine Linux镜像报错errors: 15 distinct packages available

1.执行报错 执行docker build -t 镜像:版本 -f Dockerfile . 报错: 2.查看网上的解决思路 网上文档解决思路: 这边我做了一下改变把这些写入了dockerfile 加了几个RUN RUN rm -rf /var/cache/apk RUN mkdir -p /var/cache/apk RUN apk update -v 发现还…