Java中的多线程(Thread)(一)概念篇

2023-11-16

学习目标

知识点 要求

多线程介绍

了解

线程的创建

掌握

线程的使用

掌握

线程的优先级

掌握

守护线程

掌握

线程同步

掌握

线程并发协作

掌握

一、 多线程介绍

  1. 多线程的基本概念

“程序(Program)”是一个静态的概念,一般对应于操作系统中的一个可执行文件,比如:我们要启动酷狗听音乐,则需要执行酷狗对应的的可执行程序。当我们双击酷狗的可执 行程序后操作系统会将该程序加载到内存中,开始执行该程序,于是产生了“进程”。

1.1进程

执行中的程序叫做进程(Process),是一个动态的概念。其实进程就是一个在内存中独 立运行的程序空间 。如正在运行的写字板程序就是一个进程。

进程是程序的一次动态执行过程, 占用特定的地址空间。

每个进程由 3 部分组成:cpu、data、code。每个进程都是独立的,保有自己的 cpu 时间,代码和数据,即便用同一份程序产生好几个进程,它们之间还是拥有自己的这 3 样东西,这样的缺点是:浪费内存,cpu 的负担较重。

多任务(Multitasking)操作系统将 CPU 时间动态地划分给每个进程,操作系统同时执行多个进程,每个进程独立运行。以进程的观点来看,它会以为自己 独占 CPU 的使用权。

进程的查看

Windows 系统: Ctrl+Alt+Del,启动任务管理器即可查看所有进程。

1.3线程

一个进程可以产生多个线程。同多个进程可以共享操作系统的某些资源一样,同一进程 的多个线程也可以共享此进程的某些资源(比如:代码、数据),所以线程又被称为轻量级进程(lightweight process)。

一个进程内部的一个执行单元,它是程序中的一个单一的顺序控制流程。

一个进程内部的一个执行单元,它是程序中的一个单一的顺序控制流程。

一个进程中的多个线程共享相同的内存单元/内存地址空间,可以访问相同的 变量和对象,而且它们从同一堆中分配对象并进行通信、数据交换和同步操作。

一个进程中的多个线程共享相同的内存单元/内存地址空间,可以访问相同的 变量和对象,而且它们从同一堆中分配对象并进行通信、数据交换和同步操作。

线程的启动、中断、消亡,消耗的资源非常少。

2.线程和进程的区别

  1. 线程在进程中运行的。
  2. 一个进程可以包含多个线程。
  3. 一个进程可以包含多个线程。

  4. 进程要比线程消耗更多的计算机资源。

  5. 进程间不会相互影响,因为它们的空间是完全隔离的。而进程中的一个线程挂掉将 导致整个进程挂掉。

  6. 进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等 它结束,才能使用这一块内存。

  7. 一个进程如果只有一个线程则可以被看作单线程的,如果一个进程内拥有多个线 程,进程的执行过程不是一条线(线程)的,而是多条线(线程)共同完成的。

3.什么事并发

并发是指在一段时间内同时做多个事情。当有多个线程在运行时,如果只有一个  CPU,这种情况下计算机操作系统会采用并发技术实现并发运行,具体做法是采用“ 时间片轮询算法”,在一个时间段的线程代码运行时,其它线程处于就绪状。这种方式我们称之为并发(Concurrent)。

4.线程执行的特点

4.1方法的执行特点

 

4.2线程的执行特点

5.什么是主线程以及子线程 

5.1主线程

当Java 程序启动时,一个线程会立刻运行,该线程通常叫做程序的主线程(main thread),即 main 方法对应的线程,它是程序开始时就执行的。

Java 应用程序会有一个 main 方法,是作为某个类的方法出现的。当程序启动时,该方法就会第一个自动的得到执行,并成为程序的主线程。也就是说,main   方法是一个应用的入口,也代表了这个应用的主线程。JVM 在执行 main 方法时,main 方法会进入到栈内存,JVM 会通过操作系统开辟一条 main 方法通向 cpu 的执行路径,cpu 就可以通过这个路径来执行main 方法,而这个路径有一个名字,叫 main(主)线程

主线程的特点:

它是产生其他子线程的线程。

它不一定是最后完成执行的线程,子线程可能在它结束之后还在运行。

5.2子线程

在主线程中创建并启动的线程,一般称之为子线程。

二、线程的创建 

在 Java 中使用多线程非常简单,我们先学习如何创建线程,然后再结合案例深入剖析线程的特性。

1.通过继承Thread 类实现多线程

在 Java 中负责实现线程功能的类是 java.lang.Thread 类。继承 Thread 类实现多线程的步骤:

继承 Thread 类定义线程类。

重写 Thread 类中的 run( )方法。run( )方法也称为线程体。

实例化线程类并通过 start()方法启动线程。

package 包1;

public class TestThread01 extends Thread{
//    构造无参构造方法
    /*
    * 因为这里继承了线程类,作为线程的子类,所以它在调用构造方法的时候,会返回当前对象(线程)的getName
    * */
    public TestThread01() {
        System.out.println(this.getName());
    }
//  当前线程的线程体
    @Override
    public void run() {
        System.out.println(this.getName()+"线程开始! ");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for(int i =0; i<10 ;i++){
            System.out.println(this.getName()+"----"+i+"执行!");
        }
        System.out.println(this.getName()+"线程结束!!");
    }
// 主方法 (方法中一共有三个线程,thread.main、thread、thread1)

    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName()+"线程开始!");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
//      这里其实就是普通的实例化过程,在这里就是创建线程
        TestThread01 test01 = new TestThread01();
//       启动线程
        test01.start();

        TestThread01 test02 = new TestThread01();
        test02.start();

        System.out.println("主线程结束!");
    }
}

运行结果:

我们可以看到,我们实例化了 两个 线程类 的对象,她们在运行过程中就好比争风吃醋的女生一样不断的抢占着进程资源。

2.通过实现Runnable 接口实现多线程

public class TestThread02 implements Runnable{
    public TestThread02() {
    }
    /*
     * 构建当前线程的线程体
     * */
    @Override
    public void run() {
        for(int i = 0; i<10 ; i++){
            System.out.println(Thread.currentThread().getName()+"---"+i);
        }
    }
    public static void main(String[] args) {
        //因为是实现接口的形式,所以这几=实例化对象的时候并没有同时创建线程
        TestThread02 testThread02 = new TestThread02();
//        我们定义一个新的线程,把对象以参数的方式传递进去
        Thread thread = new Thread(testThread02);
        thread.start();

        TestThread02 testThread02_1 = new TestThread02();
        Thread thread1 = new Thread(testThread02_1);
        thread1.start();
    }
}

 运行结果:

 两个线程其实也是在抢占进程中的资源在运行!

3.线程的执行流程

4.线程的生命周期

一个线程对象在它的生命周期内,需要经历 5 个状态。

新生状态(New)

用 new 关键字建立一个线程对象后,该线程对象就处于新生状态。处于新生状态的线程有自己的内存空间,通过调用 start 方法进入就绪状态。

就绪状态(Runnable)

处于就绪状态的线程已经具备了运行条件,但是还没有被分配到  CPU,处于“线程就绪队列”,等待系统为其分配  CPU。就绪状态并不是执行状态,当系统选定一个等待执行的 Thread 对象后,它就会进入执行状态。一旦获得 CPU,线程就进入运行状态并自动调用自己的 run 方法。有 4 中原因会导致线程进入就绪状态:

运行状态(Running)

在运行状态的线程执行自己 run  方法中的代码,直到调用其他方法而终止或等待某资源而阻塞或完成任务而死亡。如果在给定的时间片内没有执行结束,就会被系统给换下来回 到就绪状态。也可能由于某些“导致阻塞的事件”而进入阻塞状态。

阻塞状态(Blocked)

阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪)。有 4  种原因会导致阻塞:

执行 sleep(int millsecond)方法,使当前线程休眠,进入阻塞状态。当指定的时间到了后,线程进入就绪状态。

执行 wait()方法,使当前线程进入阻塞状态。当使用 nofity()方法唤醒这个线程后, 它进入就绪状态。

线程运行时,某个操作进入阻塞状态,比如执行 IO 流操作(read()/write()方法本身就是阻塞的方法)。只有当引起该操作阻塞的原因消失后,线程进入就绪状态。

join()线程联合: 当某个线程等待另一个线程执行结束后,才能继续执行时,使用join()方法。

死亡状态(Termiated)

死亡状态是线程生命周期中的最后一个阶段。线程死亡的原因有两个。一个是正常运行的线程完成了它 run()方法内的全部工作; 另一个是线程被强制终止,如通过执行 stop() 或 destroy()方法来终止一个线程(注:stop()/destroy()方法已经被 JDK 废弃,不推荐使用)。当一个线程进入死亡状态以后,就不能再回到其它状态了。

下一章是线程的使用

  1. 新建线程:调用 start()方法,进入就绪状态;
  2. 阻塞线程:阻塞解除,进入就绪状态。
  3. 运行线程:调用 yield()方法,直接进入就绪状态;
  4. 运行线程:JVM 将 CPU 资源从本线程切换到其他线程。

 

 

 

 

 

 

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

Java中的多线程(Thread)(一)概念篇 的相关文章

  • 如何用Java写入OS系统日志?

    Mac OS 有一个名为 Console 的应用程序 其中包含记录的消息 错误和故障 我相信 Windows 中的等效项是事件查看器 我想 Linux 上也有一个 但我不知道它是什么 也不知道它在哪里 是否可以像这样从 Java 输出获取消
  • 正确配置JDK环境变量后仍然找不到java命令

    我在 Windows 虚拟机启动时安装 JDK 使用 cloudinit 用户数据将 PowerShell 脚本传输到 Windows 计算机 然后运行该脚本来安装 JDK softwares Get ItemProperty HKLM S
  • 如何防止在 CXF Web 服务客户端中生成 JAXBElement

    我正在尝试使用 CXF 创建一个 Web 服务客户端来使用 WCF Web 服务 当我使用 wsdl2java 时 它生成具有 JAXBElement 类型而不是 String 的对象 我读到有关使用 jaxb bindings xml 文
  • H264 字节流到图像文件

    第一次来这里所以要温柔 我已经在给定的 H 264 字节流上工作了几个星期 一般注意事项 字节流不是来自文件 它是从外部源实时提供给我的 字节流使用 Android 的媒体编解码器进行编码 当将流写入扩展名为 H264的文件时 VLC能够正
  • Java中定义类型后同时初始化多个变量?

    这里需要一些语法方面的帮助 我正在尝试在定义类型后重新初始化多个变量 例如 int bonus sales x y 50 这工作正常 但是我想稍后在程序中将不同的值放入其中一些变量中 但我收到语法错误 bonus 25 x 38 sales
  • 在 Android 中绘制一条带有弯曲边缘的线

    I am using canvas drawLine to draw some line in android but the lines are too sharp but i need a curved edges 这里的 1 是我所拥
  • 空 EntityManager/EJB 注入 MDB

    我有一个消息驱动 bean MDB 部署到 WebLogic 12 1 3 我尝试使用 PersistenceContext 注释将实体管理器注入 MDB 但实体管理器为空 我还尝试注入一个简单的无状态会话 bean 它也是空的 但是 Me
  • 代码编译期间遇到警告消息“使用或覆盖已弃用的 API”

    我编译了我的程序并收到以下错误 我该如何解决呢 Note ClientThreadClients java uses or overrides a deprecated API Note Recompile with Xlint depre
  • Codility 钉板

    尝试了解 Codility NailingPlanks 的解决方案 问题链接 https app codility com programmers lessons 14 binary search algorithm nailing pla
  • 更改 JTextPane 的大小

    我是Java新手 刚刚在StackOverflow中找到了这段代码 ResizeTextArea https stackoverflow com questions 9370561 enabling scroll bars when jte
  • 如何在Gradle中支持多种语言(Java和Scala)的多个项目?

    我正在尝试将过时的 Ant 构建转换为 Gradle 该项目包含约50个Java子项目和10个Scala子项目 Java 项目仅包含 Java Scala 项目仅包含 Scala 每个项目都是由 Java 和 Scala 构建的 这大大减慢
  • 如何在命令提示符中检查 JAVA_OPTS 值?

    我们的应用程序部署 JBoss 服务器然后抛出错误 PermGen space 然后在 jboss bat 和配置文件中设置 permgen 变量中的 java OPTS JAVA OPTs 中是否有值 assige 如何检查 如何在命令提
  • Java 中 static 关键字如何工作?

    我正在阅读Java教程 http docs oracle com javase tutorial index html从一开始我就有一个问题static字段或变量上的关键字 作为Java said here http docs oracle
  • 尝试在空对象引用上调用虚拟方法“java.lang.String org.jsoup.nodes.Element.ownText()”

    我正在使用下面的代码来获取版本名称 from 应用商店通过使用 jsoup 我正在获取详细信息 但它引发了一些异常 我的代码是 public class ForceUpdateAsync extends AsyncTask
  • 更改 RowLayout SWT Java 中元素的顺序

    有没有办法更改在行布局中创建的元素的顺序 我想将其显示在元素中 首先显示 例如 如果我创建 element1 则 element2 element3 element4 我想看到的布局为 元素4 元素3 元素2 元素1 这意味着最后创建的元素
  • XSLT:我们可以使用abs值吗?

    我想知道在 XSLT 中我们是否可以使用 math abs 我在某处看到过这个 但它不起作用 我有类似的东西
  • 在多模块项目中访问绑定适配器

    我有一个多模块项目 其中应用程序模块包含我的绑定适配器 而我的功能模块取决于我的应用程序模块 因为它是动态功能模块 应用程序 包含绑定适配器 gt 动态功能模块 存在布局的地方 我在所有模块中启用了数据绑定和 kapt 我无法成功构建应用程
  • 膨胀类片段 InflateException 二进制 XML 文件时出错

    我正在使用 Material Design 和 NavigationDrawer 布局等设计我的第一个应用程序 但我遇到了一个问题 该应用程序非常简单 它只显示文本 并且基于 Android Studio 中提供的模板 尝试启动我的应用程序
  • C++ 中的 Java ArrayList [重复]

    这个问题在这里已经有答案了 在Java中我可以做 List
  • Java:基于 Web 的应用程序中的单例类实例

    我在 Web Application 中有这个 Singleton 类 public class MyDAO private static MyDAO instance private MyDAO public static MyDAO g

随机推荐

  • Apache PLC4X 副总裁宣布个人停止对项目提供免费支持;Linux 5.17 增加对中国 Soc 的支持;IPython 8.0 发布

    整理 宋彤彤 责编 屠敏 开源吞噬世界的趋势下 借助开源软件 基于开源协议 任何人都可以得到项目的源代码 加以学习 修改 甚至是重新分发 关注 开源日报 一文速览国内外今日的开源大事件吧 一分钟速览新闻点 开源大新闻 因缺少资金 Apach
  • 网络工程毕业设计选题大全 毕设题目推荐

    文章目录 0 简介 1 如何选题 2 最新网络工程选题 2 1 Java web SSM 系统 2 2 大数据方向 2 3 人工智能方向 2 4 其他方向 4 最后 0 简介 学长搜集分享最新的网络工程专业毕设毕设选题 难度适中 适合作为毕
  • Aspose.Diagram for Java V22.5

    Aspose Diagram for Java V22 5 Aspose Diagram for Java 是一个强大的 Microsoft Visio 文件处理 API 它提供了通用功能 例如创建 操作和转换本机 Visio 格式以及一些
  • 大数据学习脑图以及容易消化的入门教程

    近些年 大数据的火热可谓是技术人都知道啊 很多人呢 也想学习大数据相关 所以 这里分享几个大数据脑图 希望可以让你清楚明白从哪里入门大数据 知道该学习以及掌握哪些知识点 大数据相关脑图 想要在大数据这个领域汲取养分 让自己壮大成长 分享方向
  • sklearn中cross_val_score、cross_val_predict的用法比较

    交叉验证的概念 直接粘贴scikit learn官网的定义 scikit learn中计算交叉验证的函数 cross val score 得到K折验证中每一折的得分 K个得分取平均值就是模型的平均性能 cross val predict 得
  • 排列组合理解SQL JOINS的几种情况

    一 JOIN的三种方式 1 left join 2 right join 3 full join 二 Join的结果 两个集合的join可能出现多少中结果呢 利用数学里的排列组合知识很容易算出来 如上图 join相当于把两个集合分为三个部分
  • opencv光流Optical Flow

    光流Optical Flow 现在四轴飞行器越来越火 如何在室内进行定位呢 不同于传统四轴的姿态控制 电机驱动 室外定位 都有了一套完整的方案 室内定位还是没有完全成熟 目前大四轴可以利用的GPS定高 小四轴比较成熟的也就是光流方案了 先看
  • springboot之接受数据的三种方式:@requestParam,@requestBody和@PathVariable

    前言 作为后端 我们经常需要和前端进行数据之间的交互 而我们从前端获取的方式主要有下面几种 路径中的数据 例如localhost user 2 这时我们需要获得路径上的数字2 存放到url头里的参数例如localhost user name
  • pytorch入门的入门

    DATASETS DATALOADERS 两个有用的 torch utils data DataLoader and torch utils data Dataset 其中Dataset存储样本和标签 就是图片和真值 而DataLoader
  • JDK7下载

    JDK7下载 JDK1 7下载可选择window版和linux版 下载说明文档 判断系统是64位还是32位 Linux下选tar gz好还是rpm 1 windows版JDK1 7 64位下载 点击下载 jdk 7u67 windows x
  • MATLAB/Simulink 使用记录

    1 InitFcn 仿真模块全局变量初始化 启动Run之后可以添加至工作区 右键 Model Perprities Callbacks InitFcn 2 子模块参数输入 右键模块 Mask Edit Mask Parameter Dial
  • java 中各种数据类型的互相转换的常用方法

    java 各种数据类型的互相转换 1 StringBuilder转化为String String str abcdefghijklmnopqrs StringBuilder stb new StringBuilder str 2 整型数组转
  • openCV 3.4.7在Visual Studio 2015中配置

    准备 1 安装openCV3 4 7 https opencv org releases 2 安装visual studio 2015 http c biancheng net view 453 html 开始配置 1 计算机 右键 属性
  • 北邮22级信通院数电:Verilog-FPGA(3)实验“跑通第一个例程”modelsim仿真及遇到的问题汇总(持续更新中)

    北邮22信通一枚 跟随课程进度更新北邮信通院数字系统设计的笔记 代码和文章 持续关注作者 迎接数电实验学习 获取更多文章 请访问专栏 北邮22级信通院数电实验 青山如墨雨如画的博客 CSDN博客 注意 本篇文章所有绝对路径的展示都来自上一篇
  • C语言回调函数学习

    作者 杨硕 华清远见嵌入式学院讲师 对指针的应用是C语言编程的精髓所在 而回调函数就是C语言里面对函数指针的高级应用 简而言之 回调函数是一个通过函数指针调用的函数 如果你把函数指针 函数的入口地址 传递给另一个函数 当这个函数指针被用来调
  • FBX SDK 开发环境配置 visual studio 2022

    FBX Adaptable File Formats for 3D Animation Software Autodesk 下载windows的sdk并安装 创建一个c console 工程 设置include目录 添加预处理宏 FBX S
  • 【前端】html+js+css开发入门超详细介绍

    文章目录 一 HTML 1 1 第一个页面 1 2 所有标签都来一遍 1 3 超链接 1 4 发邮件 1 5 description list描述列表 1 6 blockquote块引用 1 7 linequote 1 8 address
  • dns改成什么网速快_这个DNS服务器不仅更快而且安全

    DNS也就是域名解析服务器 这个东西的存在 使我们上网变得非常方便 再也不需要去记下复杂的IP了 而同样 DNS也影响着我们的网速 那么今天 小编就给大家推荐一个DNS服务器 这个DNS服务器不仅更快 而且更加安全 一起来看看吧 中国互联网
  • gson反序列化成data class时的坑

    前言 在Android开发中 gson是很常用的用来处理json的三方库 它是由Google维护的 一直以来都比较稳定 至少在使用Java开发时是这样的 但是 gson对Kotlin的data class的支持就不是很完善了 会有一些坑 下
  • Java中的多线程(Thread)(一)概念篇

    学习目标 知识点 要求 多线程介绍 了解 线程的创建 掌握 线程的使用 掌握 线程的优先级 掌握 守护线程 掌握 线程同步 掌握 线程并发协作 掌握 一 多线程介绍 多线程的基本概念 程序 Program 是一个静态的概念 一般对应于操作系