Java编程--多线程/多线程的构造/多线程的属性/线程中断/线程的状态/线程等待

news2024/11/26 20:21:15

       前言 

        逆水行舟,不进则退!!!     


       进程与线程

        什么是进程?           

        答:进程是操作系统分配资源的最小单元,它是运行中的程序的实例,或者说,是应用程序的一次动态执行。例如,当你在电脑上打开一个软件,如浏览器,操作系统就会为这个软件创建一个新的进程。在这个进程中,浏览器将获取CPU时间、内存等系统资源来执行它的功能。每个进程都具有独立的内存单元,这意味着每个进程之间相互独立,互不干扰。以一个生活中的例子来解释,进程就好比你去银行转账,你对银行来说就是一个进程。银行为你提供了接待员、转账人员、银行电脑等资源来为你完成转账这一整个服务流程。而银行对其他人的服务并不干扰你。

        什么是进程控制块?       

        答:进程控制块(PCB)是操作系统中的关键数据结构,主要用于描述和控制进程。它包含了标识进程信息的必要数据,如进程标识符、进程状态、程序计数器、寄存器、内存分配情况、打开文件列表以及进程优先级等。每个进程都有一个唯一的进程控制块,它是进程存在的唯一标识,操作系统通过这个控制块找到进程并进行管理和调度。例如,当需要暂停当前进程并切换到另一个进程时,就需要保存当前进程的上下文信息,包括CPU寄存器、程序计数器、堆栈指针等,而这些信息都存储在PCB中。因此,PCB是操作系统对进程进行具体识别和控制的依据,也是进程的集中特性反映。

        什么是线程?             

        答:线程是进程内部的一个执行单元,它负责执行进程中的程序。一个进程中至少有一个线程,当然,一个进程也可以拥有多个线程,这样的程序也被称为多线程程序。线程有着自己的进程控制块(PCB),但是它们并没有独立的地址空间,而是与所属进程共享同一个地址空间。这意味着,每个线程进行数据交换时,都可以直接访问进程内的共享数据,这大大提高了数据访问的效率。

        举个生活中的例子,你正在准备一顿丰盛的晚餐,做菜、切菜、洗菜等各个环节都可以看作是线程,它们共同构成了准备晚餐这个进程。其中,切菜和炒菜这两个线程之间可能需要进行数据交换,由于它们在同一个进程中,因此这种数据交换非常快速且高效。

        进程与线程的区别是什么?

        答:

                1,进程是计算机系统分配资源的基本单位;线程是计算机系统调度和分派的基本单位。

                2,进程是一个动态概念,每个进程都有自己的地址空间和系统资源;线程是进程中的一个执行单元,是进程中的一个实体,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器、寄存器和栈);

                3,进程间相互独立,互不干扰;线程可与同属一个进程的其他线程共享进程所拥有的全部资源,包括进程的堆 和 方法区 资源。

                4,进程间切换,时空开销大:空间开销主要源于上下文信息的保存与恢复,由于每个进程拥有自己独立的地址空间,因此,在进程切换时,需要保存和恢复大量的上下文信息,包括程序计数器、寄存器以及内存映射等。时间开销也不容忽视。进程间的切换涉及到CPU状态的保存和恢复,这一过程需要耗费一定的时间。例如,在单核系统中,如果需要在进程A和进程B之间进行切换,那么首先需要将CPU的状态保存到进程A的上下文中,然后再加载进程B的上下文到CPU中。

相比之下,线程间切换则相对轻量。因为同一进程内的多个线程共享相同的地址空间,所以线程切换只需保存和恢复少量的上下文信息,如PC指针和寄存器的值。此外,线程的创建也比进程简单得多,只需要确定PC指针和寄存器的值,并给线程分配一个栈用于执行程序。这也是多线程被广泛应用的原因之一,它能够有效提高系统的并发性和性能。

        

        什么是多线程?                

        答:多线程是指在一个程序中同时运行多个线程来完成不同的工作,以提高程序的效率和性能。线程是进程中的一个执行单元,它是进程内的一个执行流程,也是程序执行的最小单位。一个进程中至少有一个线程,当然,一个进程也可以拥有多个线程,这样的程序也被称为多线程程序。多线程技术使得程序可以同时处理多个任务,从而提高了程序的效率和响应速度。在应用程序中,如果要对线程进行调度,最直接的方式就是设置线程的优先级。优先级越高的线程获得CPU执行的机会越大,而优先级越低。

         


       线程的创建

        1,继承Thread,重写run() 方法;

class MyThread extends Thread {

    // 重写run() 方法
    @Override
    public void run() {
        while(true) {
            System.out.println("hello world");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class ThreadDemo1 {
    public static void main(String[] args) {
        Thread t = new MyThread();
        t.start();
        //t.run();

        while(true) {
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

        

        2,实现Runnable接口

//Runnable的作用 是表述了一个 “要执行的任务”, run方法就是执行任务的细节
class MyRunnable implements Runnable {

    @Override
    public void run() {
        System.out.println("hello thread");
    }
}

public class ThreadDemo1 {
    public static void main(String[] args) {
        //这只是描述了个任务
        Runnable runnable = new MyRunnable();
        //然后 把任务交给线程来执行
        Thread t = new Thread(runnable);
        t.start();

        这种写法是 解耦合,目的就是为了让线程 和 线程要干的活 之间分离开。
        未来如果要该代码,不用多线程了,使用多进程,或者此线程池,或者协程....此时代码改动比较小。
        */
    }

}

       

        3,使用匿名内部类,继承Thread

public class ThreadDemo3 {
    public static void main(String[] args) {
// 创建了一个Thread 的子类,(子类没有名字),创建了子类的实力,并且让 t 引用指向该实例
        Thread t = new Thread() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        };
        t.start();
    }
}

        4,使用匿名内部类,实现Runnable;

public class ThreadDemo4 {
    public static void main(String[] args) {
// 这个写法 和 使用匿名内部类 继承 Thread 本质相同,
//只不过是把实现Runnable 的任务交给了匿名内部类的语法

// 此处是创建了一个类,实现Runnable, 同时创建了类的实例,并且传给了Thread的构造方法。
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hell0");
            }
        });
        t.start();
    }
}

        5,使用lambda表达式实现

public class ThreadDemo5 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            System.out.println("hello");
        });
        t.start();
    }
}


       线程的属性
属性获取方法
IDgetId()
名称getName()
状态getState()
是否后台线程isDaemon()
是否存活isAlive()
是否被中断isInterrupted()

getId() 方法:getId() 方法返回的是该线程的唯一标识符,
getName() 方法:该方法可以返回当前线程的名称。并不是指向该线程的引用的名称。
IsDaemon() 方法:返回当前线程是否为后台线程。isDaemon 守护线程就是后台线程,切换到后台运行的线程就是后台线程

 


       线程中断      

        中断一个线程,中断的意思是: 不是让线程立即就停止,而是通知线程,你应该要停止了,是否真的停止,取决于线程这里具体的代码写法。

       

1,使用一个标志位,来控制线程是否终止。

2,使用 Thread 自带的标志位,来进行判定,

        为什么sleep要清除标志位?

                答:唤醒之后,线程到底要终止还是不要终止,到底是立即终止还是稍后终止,就把选择权交给程序员了。


       线程的状态      

1,NEW  创建了Thread对象,但是还没有调用start(内核里还没有创建对应的PCB);

2,TERMINATED   表示内核中的PCB已经执行完毕了(PCB 释放了),但是Thread对象还在。

3,RUNNABLE  可运行的线程,包括以下两种:

        a)正在CPU上执行的线程。

        b)在就绪队列中,可以随时去CPU上执行

4,WAITING

5,  TIMED_WAITING

6,  BLOCKED

        4、5、6都是阻塞,表示线程PCB正在阻塞队列中。只是阻塞的原因不同。


       线程等待

        有时,我们需要等待一个线程完成它的工作后,才能进行自己下一步工作。这就是线程等待存在的意义。

方法说明
public void join()等待线程结束
public void join(long millis)等待线程结束,最多等 millis 毫秒
public void join(long millis, int nanos)同理,但可以更高精度

        join()无参时, 就是死等。有参数的 join 方法 是制定一个最大等待时间。


      

        注:如果主线程调用t.join() 的时候,t 线程已经结束了,join不会阻塞,会立即返回。


        我是专注学习的章鱼哥~

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

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

相关文章

阿里云双11活动时间、活动入口、优惠政策详细解读

阿里云2023年双11推出了金秋云创季活动,作为年终最大的一次优惠促销活动,活动力度还是很不错的,可以领取上云满减券礼包,百科产品满减折上折,2核2G3M云服务器1年99元,新老同享,续费同价&#xf…

【实战Flask API项目指南】之三 路由和视图函数

实战Flask API项目指南之 路由和视图函数 本系列文章将带你深入探索实战Flask API项目指南,通过跟随小菜的学习之旅,你将逐步掌握 Flask 在实际项目中的应用。让我们一起踏上这个精彩的学习之旅吧! 前言 当小菜踏入Flask后端开发的世界时&…

3.Docker的客户端指令学习与实战

1.Docker的命令 1.1 启动Docker(systemctl start docker) systemctl start docker1.2 查看docker的版本信息(docker version) docker version1.3 显示docker系统范围的信息(docker info) docker info1.4…

Qt QtCreator添加自定义注释

在写代码的时候我们为了规范化,一般会加文件注释、类注释和函数注释;用注释来说明我们的代码,也方便模块化开发,那么我们在写注释的时候经常会写一些重复的内容,我们会复制粘贴。这样一来二去,就显得很繁琐…

持续进化,快速转录,Faster-Whisper对视频进行双语字幕转录实践(Python3.10)

Faster-Whisper是Whisper开源后的第三方进化版本,它对原始的 Whisper 模型结构进行了改进和优化。这包括减少模型的层数、减少参数量、简化模型结构等,从而减少了计算量和内存消耗,提高了推理速度,与此同时,Faster-Whi…

如何查看WiFi密码

本文分享一下手机和电脑上如何查看已经连接过的WiFi的密码,然后好分享给他人。 手机上分享wifi密码很简单,步骤如下: 生成二维码,读取WiFi密码 1、首先,在“设置”中找到“无线网络”,点击需要查找密码的Wi…

旅游业为什么要选择VR全景,VR全景在景区旅游上有哪些应用

引言: VR全景技术的引入为旅游业带来了一场变革。这项先进技术不仅提供了前所未有的互动体验,还为景区旅游文化注入了新的生机。 一.VR全景技术:革新旅游体验 1.什么是VR全景技术? VR全景技术是一种虚拟现实技术&am…

VB.NET—窗体引起的乌龙事件

目录 前言: 过程: 总结: 升华: 前言: 分享一个VB.NET遇到的一个问题,开始一直没有解决,这个问题阻碍了很长时间,成功的变成我路上的绊脚石,千方百计的想要绕过去,但事与愿违怎么也绕不过去,因为运行不了…

HiveSQL中last_value函数的应用

一、背景 在以下数据中如何实现对每一个列按照更新时间取最新的非null值? 1 a a null 202301 202301 1 b b null null 202302 1 null c null null 202303 1 d null null null 202304如何实现…

速学数据结构 | (超级干货)业界程序员公认的实现栈最简单的方法!太简单了

🎬 鸽芷咕:个人主页 🔥个人专栏:《Linux深造日志》《C干货基地》 ⛺️生活的理想,就是为了理想的生活! 📋 前言 🌈hello! 各位铁铁们大家好啊,今天来给大家更新一下栈这个数据结构,…

【六、http】go的http的客户端重定向

一、http的重定向 重定向过程:客户浏览器发送http请求----》web服务器接受后发送302状态码响应及对应新的location给客户浏览器–》客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址----》服务器根据此请求寻…

3.4_Linux-浏览文件系统

1.Linux 文件系统 如果你刚接触Linux系统,可能就很难弄清楚Linux如何引用文件和目录,对已经习惯Microsoft Windows操作系统方式的人来说更是如此。在继续探索Linux系统之前,先了解一下它的布局是有好处的。 你将注意到的第一个不同点是&…

高级 Python:函数

伊利亚拉扎列维奇 一、说明 读完标题后,你可能会问自己一些类似的事情,“Python 中的函数是一个高级概念?如何?所有课程都引入了功能作为语言的基本块。你既是对的,也是错的。 大多数关于 Python 的课程都将函数作为基…

3.21每日一题(区间在现求定积分)

当发现一个定积分,原函数根本找不出来时,可以用变量代换:区间再现!!!

nodejs+vue高校食堂物流管理系统-毕业设计

1.本课题的研发内容是:研制开发一个基于 的高校食堂物流管理系统,使用B/S架构,使用MVC模式开发,实现对高校食堂物流各流程的统一管理。 2.课题的研发要求:实现一个基于 的高校食堂物流管理系统的基本功能和主要流程&am…

【STL】:list的模拟实现

朋友们、伙计们,我们又见面了,本期来给大家解读一下有关list的模拟实现,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏:C语言:从入门到精通 数据…

【报错-已解决】Resource tagsets not found.

最近在接触nltk,已经在电脑里download nltk.data了,但程序还是报错Resource tagsets not found. 在电脑里查找tagset,发现tagset文件没有解压。 对tagset压缩包进行解压,并确认解压后的文件夹文件路径没有重复(tagsets)&#xf…

深入了解 CPU 的型号、代际架构与微架构

大家好,我是飞哥! 在 10 月 16 号的时候,Intel 正式发布了第 14 代的酷睿处理器。但还有很多同学看不懂这种发布会上发布的各种 CPU 参数。借着这个时机,我给大家深入地讲讲 CPU 的型号规则、代际架构与微架构方面的知识。 CPU 在…

redis教程 一 redis中的常用命令

文章目录 redis常见命令Redis数据结构介绍redis通用命令String类型String的常见命令Key结构 Hash类型List类型Set类型SortedSet类型 redis常见命令 Redis数据结构介绍 Redis是一个key-value的数据库,key一般是String类型,不过value的类型多种多样&…

IIS中间件漏洞----DotNetScan 工具

用DotNetScan 工具把目标网站IP,端口填写下。找到IIS的网站后就可进行操作上传。 也可以使用IISPutScanner工具 上传文件 利用解析漏洞 利用漏洞的前提条件:网站根目录可写入