【多线程】线程(线程的概念+线程的创建)

文章目录

  • 线程
    • 一、线程的概念
      • 1.引入线程的目的
      • 2.什么叫线程(Thread)
          • 1.线程的特点:
          • 2.进程和线程的区别(面试题):
          • 3.Java的多线程编程
    • 二、创建线程
      • 1.继承Thread重写run
          • 入口方法:
          • 使用jconsole
          • sleep
      • 2.实现Runnable重写run
      • 3.使用匿名内部类创建
      • 4.使用lambda表达式创建

线程

C++的生态鼓励多进程编程,而在Java的生态中,更鼓励多线程编程

一、线程的概念

1.引入线程的目的

​ 引入多进程的目的,就是为了实现并发编程。但是进程太“重”,导致开销大、效率低。创建、销毁或者调度一个进程,消耗的时间都较多。主要消耗在申请资源上面。

​ 前文提到,进程是系统资源分配的基本单位。分配的消耗很大。

​ 例如分配内存操作:操作系统内部的数据结构,会把空闲的内存分块管理好。当我们进行申请内存时,操作系统就会从这个数据结构中,找到一块大小合适的空闲内存,返回给对应的进程。虽然数据结构会提高效率,但是由于要管理的内存很多,相比之下依然耗时。

如果进行频繁的创建和销毁进程,这时开销就不容忽视。

为了解决这个问题,就引入了线程(Thread)。

2.什么叫线程(Thread)

  • 线程也叫”轻量级进程“,创建、销毁、调度线程要比进程要快。

  • 线程依附于进程,不能独立存在。进程包含一个/多个线程。

  • 线程是调度执行的基本单位。

一个进程可以用一个或多个PCB来表示,每个PCB对应到一个线程。

每一个线程,都有状态、优先级、上下文、记账信息等等来辅助调度。

pid、内存指针、文件描述符表是共用的。

1.线程的特点:

1.每个线程都可以独立的在CPU上进行调度。

2.同一个进程的多个线程之间,共用同一分内存空间和文件资源。

  • 因此在创建线程时,不需要重新申请资源,直接复用之前分配给进程的资源。省去了资源分配的开销,提高了效率

3.当线程过多,可能对引发冲突。(两个线程同时访问一个变量:线程不安全)。当一个线程发生异常时,如果没有妥善处理,容易奔溃整个进程。

2.进程和线程的区别(面试题):

1.进程包含线程,一个进程可以有一个线程或者多个线程。在开始时至少要有一个线程存在(主线程)——是和进程一起创建的

这个线程负责完成执行代码的操作,也可以根据需求,创建出多个线程。每个线程都可以独立执行不同的代码,从而实现并发编程的效果。

2.进程是系统资源分配的最小单位,线程是系统调度执行的最小单位。

3.进程和线程都是为了实现并发编程的需求,但是线程比进程更加高效

4.进程和进程之间不共享内存空间,同一个进程的线程之间共享同一份内存空间和文件资源,省去了申请资源的开销。

5.进程之间具有独立性,一个进程出问题,不影响其他进程,不相互干扰。用一个进程的不同线程之间,可能会相互影响

3.Java的多线程编程

线程是操作系统中的概念,操作系统提供了对应的API,来对线程进行操作。

为了跨平台,Java又对系统的API进行了封装(Thread类),通过Thread类创建Thread对象,从而操作系统内部的进程。

二、创建线程

1.继承Thread重写run

写一个类继承自Thread

Thread类是Java标准库内置的类,在java.long包的下面,不需要import

class MyThread extends Thread{//Java标准库内置的类,在java.long包的下面,不需要import@Overridepublic void run() {//重写父类的run方法(入口方法)System.out.println("hello thread");}
}
入口方法:

每个线程都是一个独立的执行流,都可以独立执行代码。当一个线程跑起来时,从它的入口方法开始执行代码。

当运行一个Java程序时,就是跑起来了一个Java进程。这个进程里至少存在一个线程(主线程),这个主线程的入口方法就是main方法。

定义好线程后,需要对线程进行调用。

    public static void main(String[] args) {//在主线程中创建实例Thread t = new MyThread();//start和run都是Thread的方法//run 只是描述了线程的入口(线程要做什么任务)---指路的//start 真正调用了系统API,在系统中创建出这个线程,让这个线程再调用runt.start();}

run 只是描述了线程的入口(线程要做什么任务)

相当于一个psvm,里面是要执行的内容。

start 真正调用了系统API,在系统中创建出这个线程,让这个线程再调用run

相当于手动的绿色运行小三角,有了start才能开始创建、运行线程

class MyThread extends Thread{//Java标准库内置的类,在java.long包的下面,不需要import@Overridepublic void run() {//重写父类的run方法(入口方法)while (true){System.out.println("hello thread");}}
}
public class CreatThread {public static void main(String[] args) {Thread t = new MyThread();t.start();while (true){System.out.println("hello Main");}}
}
  • 此时,主线程和t线程的两个死循环在“同时执行”。日志在交替打印

在这里插入图片描述

​ 验证了每一个线程都是一个独立的执行流,在主线程中,遇到t线程时,兵分两路。一路去执行t进程,另一路继续执行主线程。实现了并发执行。

    public static void main(String[] args) {Thread t = new MyThread();//t.start();t.run();while (true){System.out.println("hello Main");}}

​ 如果把start()给成run()。将不会创建出新的线程,只有一个主线程。在主线程中执行这个对象的方法,并且死循环,不会进入到下面的循环中。

使用jconsole

使用 jconsole来观察进程中多线程的情况。

JDK中自带的工具

在JDK的目录下 : bin/jconsole.exe

  • 启动时要保证线程已经运行。

在这里插入图片描述

一个Java进程启动后,JVM会自动创建线程来进行一系列操作(如垃圾回收、资源统计、远程方法调用等等)

sleep
  • sleep是Thread的类方法,通过类名直接调用
  • 在使用sleep时,可能会抛出受查异常,必须显示处理
       while (true){System.out.println("hello thread");try {Thread.sleep(1000);//每执行一次,休眠一秒} catch (InterruptedException e) {throw new RuntimeException(e);}}

在循环体中加sleep,进行休眠。

两个线程都休眠1000毫秒,时间到了之后,谁先执行是“随机”的。操作系统对于多个线程的调度顺序是”随机“的。

概率不均等,取决于调度器的具体实现

2.实现Runnable重写run

Runnable是一个interface接口

Runnable表示的是一个“可以运行的任务”,这个任务是交给线程负责执行,还是交给其他的实体执行。Runnable本身并不关心。

class MyRunnable implements Runnable{@Overridepublic void run() {while (true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
public class demo1 {public static void main(String[] args) throws InterruptedException {Runnable runnable = new MyRunnable();//将任务放到线程里面执行Thread t = new Thread(runnable);t.start();//还是通过start来创建线程while (true){System.out.println("hello main");Thread.sleep(1000);}}

使用继承Thread写法和实现Runnable接口写法的区别,主要是解耦合

创建一个线程,需要进行两个关键操作:

1.明确线程要执行的任务

任务本身不一定和线程强相关,把任务提取出来,随时对代码进行修改。 达到解耦合的效果。

2.调用系统api来创建出线程

3.使用匿名内部类创建

    public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new Runnable() {@Overridepublic void run() {while (true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}});t.start();while (true){System.out.println("hello main");Thread.sleep(1000);}}
public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new Runnable() {@Overridepublic void run() {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}});t.start();while (true) {System.out.println("hello main");Thread.sleep(1000);}}

4.使用lambda表达式创建

    public static void main(String[] args) throws InterruptedException {Thread t = new Thread(()->{while (true){System.out.println("hello thread!");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t.start();while (true){System.out.println("hello Main");Thread.sleep(1000);}}

点击移步博客主页,欢迎光临~

偷cyk的图

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

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

相关文章

Games101-光线追踪(加速结构)

Bounding Volumes 包围盒:用一个简单形状把物体包围起来,如果物体连包围盒都无法碰撞,一定无法碰撞包围盒内的物体 将长方体理解成三个不同对面形成的交集,一定是在x,y,z轴上的范围。没有旋转 Ray Inters…

适用于 Windows 10 的 10 大免费数据恢复软件

数据丢失可能是一场噩梦,尤其是在涉及重要文件和文档时。无论是由于意外删除、系统崩溃还是病毒攻击,找到适合 Windows 10 的文件夹恢复软件都可以在恢复丢失的数据方面发挥重要作用。在本指南中,我们将探索适用于 Windows 10 用户的 10 大免…

加密方法字段uuid标识

58b16292-260b-60bd-44a7-796e3ed4f20e 是uuid python实现 import uuidprint(uuid.uuid4())是的,7bff3132-952a-4338-9df4-544383e81a2a 是一个典型的UUID(Universally Unique Identifier,通用唯一识别码)格式的字符串。UUID是一…

mysql解锁表及查看表是否被锁

1、查进程,查找被锁表的那个进程的ID show processlist; 2、通过查询结果,找到要杀掉的进程,kill掉锁表的进程ID kill id; 3、查询是否锁表 show OPEN TABLES where In_use > 0; 1.delete------ 是逐行删除速度极慢,不适合…

如何使用Python中的logging模块进行日志记录?

如何使用Python中的logging模块进行日志记录? Python中的logging模块是一个强大的工具,用于记录应用程序的运行时信息。它提供了灵活的日志记录系统,允许开发者定义不同级别的日志消息,并可以选择将这些消息输出到不同的目标&…

【退役之重学Java】pom文件没啥问题但报红

复制过来的pom文件,有几处版本号报红 刚开始以为是版本号的问题,但是按道理从大佬那里复制过来的,应该不会有问题,还是检查了一下: 把项目压缩发给师傅,师傅哪里没报错好吧,我已经猜到了为什么……

MySQL操作DDL

目录 1.概述 2.数据库的增删改查 3.表的增删改查 3.1.创建和查看表结构 3.2.修改表 3.3.查看所有的表 3.4.删除表 4.用户 5.DDL在实际应用场景中的作用 5.1.数据库设计 5.2.数据库维护 ​​​​​​​5.3.数据库迁移或重置 ​​​​​​​5.4.优化性能 ​​​​​…

cesium 添加动态波纹效果 圆形扩散效果 波纹材质

一、扩展材质 /*** 水波纹扩散材质* param {*} options* param {String} options.color 颜色* param {Number} options.duration 持续时间 毫秒* param {Number} options.count 波浪数量* param {Number} options.gradient 渐变曲率*/function CircleWaveMaterialProperty(opt…

网络学习学习笔记

NETEBASE学习笔记 一.VRP系统1.四种视图模式2.基础命令 二.TCP/IP1.五层模型 一.VRP系统 1.四种视图模式 (1)< Huawei > 用户视图 【查看运行状态】 (2)[Huawei] 系统视图 【配置设备的系统参数】 system-view /sys 进入系统视图 CtrlZ/return 直接返回用户视图 (3)[Hua…

centos7升级openssl1.1.1w版本

下载 https://www.openssl.org/source/old/1.1.1/index.html 安装依赖 yum install gcc libffi-devel zlib* openssl-devel libffi-devel zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make解压、编译、安装 tar -zxvf o…

ADS1299模拟前端(AFE)代替料LHE7909

今天我和大家分享一颗国产可以代替ADS1299的料——LHE7909&#xff0c;这是一颗由领慧立芯设计生产的一款具备颅外脑电图(EEG)和心电图(ECG)应用所需的全部常用功能的模拟前端芯片&#xff0c;并且凭借其高集成度和出色的性能&#xff0c;能够创建多种可扩展的医疗仪器系统&…

Druid面试题及参考答案

1. Druid是什么?它的主要特点有哪些? Druid是一个高效的数据查询系统,主要解决的是对于大量的基于时序的数据进行聚合查询。它的主要特点包括: 实时数据摄入:Druid能够实时地摄入数据,对于流式数据的处理非常高效。高性能查询:Druid提供了快速的数据查询能力,即使是对…

【金句推荐】适合写进摘抄本的优美句子

1.人间骄阳刚好&#xff0c;风过林梢&#xff0c;彼时他们正当年少。 2.这路遥马急的人间渐行、渐远、渐无声&#xff0c;看淡若清风的现世且听、且吟、且从容。 3.一个能够升起月亮的身体&#xff0c;必然驮住了无数次日落。 4.并不可否认&#xff0c;生活磨掉了我们一部分…

数学建模-------MATLAB分支循环断点调试

1.if语句 &#xff08;1&#xff09;分段函数的引入&#xff08;这里的数据表示的是分数的不同区间对应的等级&#xff09; (1)这个就是一个十分简单的if语句&#xff0c;无论是if还是elseif后面都是不能添加任何分号的&#xff0c;这个例子就是一个分段的函数&#xff0c;在不…

mac/win使用pyinstaller打包app/exe文件,活着执行脚本,双击运行

&#x1f338; 踩坑记录 python环境最好使用虚拟环境&#xff0c;推荐使用conda管理&#xff0c;并且若本地有python环境&#xff0c;不要使用和 本地环境版本 相同的虚拟环境 这里踩坑较多&#xff0c;已经记不清楚注意点 虚拟环境python版本不要和本地环境一样 mac/win只能…

nodejs安装及环境配置

Node.js安装和环境配置在不同操作系统&#xff08;如Windows、macOS、Linux&#xff09;上会有所不同。以下是一些基本的步骤和指南来帮助你在这些常见的操作系统上安装Node.js及进行环境配置。 ### Windows #### 安装Node.js 1. **下载安装包**&#xff1a;访问Node.js官方…

清理垃圾软件哪个好?电脑清理优化4种方法

在数字时代&#xff0c;我们的电脑经常会被各种软件、程序和文件所占据&#xff0c;其中不乏一些无用甚至有害的垃圾软件。这些软件不仅占用了大量的存储空间&#xff0c;还可能拖慢电脑的运行速度&#xff0c;甚至威胁到我们的信息安全。因此&#xff0c;定期清理和优化电脑变…

紧急备考全攻略,如何短期通过PMP考试?

今年身边有很多同事朋友都要考PMP&#xff0c;而我属于这些人里”第一个吃螃蟹“的人&#xff0c;一次拿下5A&#xff0c;下面分享一下我自己备考PMP的经验。 我是根据自己的学习计划复习的&#xff0c;不能说这些方法适合所有人&#xff0c;但对备考的伙伴们来说&#xff0c;…

【考研复试上机】C++STL

文章目录 vector初始化及赋值方式vector容器内元素的访问常用函数 setset容器内元素的访问&#xff1a;set常用函数&#xff1a;multisetunordered_set stringstring常用函数&#xff1a; mapmap容器内元素的访问&#xff1a;map常用函数&#xff1a;multimapunordered_map que…

颜色识别

颜色识别 计算机视觉中的颜色识别是指计算机系统能够自动识别图像或视频中的不同颜色&#xff0c;以便进行分析、分类、跟踪和其他视觉任务。 颜色是物体的一个重要属性&#xff0c;它提供了有关对象的重要信息。 颜色识别在各种应用中都有重要作用&#xff0c;包括工业自动…