线程最最基础的知识

戳蓝字“CSDN云计算”关注我们哦!

什么是线程

试想一下没有线程的程序是怎么样的?百度网盘在上传文件时就无法下载文件了,得等文件上传完成后才能下载文件。这个我们现在看起来很反人性,因为我们习惯了一个程序同时可以进行运行多个功能,而这些都是线程的功劳。

之前的文章 进程知多少 中讲到,为了实现多个程序并行执行,引入了进程概念。现在引入线程是为了让一个程序能够并发执行。

线程的组成

线程ID:线程标识符。

当前指令指针(PC):指向要执行的指令。

寄存器集合:存储单元寄存器的集合。

堆栈:暂时存放数据和地址,一般用来保护断点和现场。

线程与进程区别

线程和进程之间的区别,我觉得可以用这个例子来看出两者的不同,进程就是一栋房子,房子住着 3 个人,线程就是住在房子里的人。进程是一个独立的个体,有自己的资源,线程是在进程里的,多个线程共享着进程的资源。

线程状态

我们看到 Java 源代码里面,线程状态的枚举有如下 6 个。

public enum State {//新建状态NEW,//运行状态RUNNABLE,//阻塞状态BLOCKED,//等待状态WAITING,//等待状态(区别在于这个有等待的时间)TIMED_WAITING,//终止状态TERMINATED;
}

下面给这 6 个状态一一做下解释。

  • NEW:新建状态。在创建完 Thread ,还没执行 start() 之前,线程的状态一直是 NEW。可以说这个时候还没有真正的一个线程映射着,只是一个对象。

  • RUNNABLE:运行状态。线程对象调用 start() 之后,就进入 RUNNABLE 状态,该状态说明在 JVM 中有一个真实的线程存在。

  • BLOCKED:阻塞状态。线程在等待锁的释放,也就是等待获取 monitor 锁。

  • WAITING:等待状态。线程在这个状态的时候,不会被分配 CPU,而且需要被显示地唤醒,否则会一直等待下去。

  • TIMED_WAITING:超时等待状态。这个状态的线程也一样不会被分配 CPU,但是它不会无限等待下去,有时间限制,时间一到就停止等待。

  • TERMINATED:终止状态。线程执行完成结束,但不代表这个对象已经没有了,对象可能还是存在的,只是线程不存在了。

线程既然有这么多个状态,那肯定就有状态机,也就是在什么情况下 A 状态会变成 B 状态。下面就来简单描述一下。

结合下图,我们 new 出线程类的时候,就是 NEW 状态,调用 start() 方法,就进入了 RUNNABLE 状态,这时如果触发等待,则进入了 WAITING 状态,如果触发超时等待,则进入 TIMED_WAITING 状态,当访问需要同步的资源时,则只有一个线程能访问,其他线程就进入 BLOCKED 状态,当线程执行完后,进入 TERMINATED 状态。

图片来源于网路,侵删

其实在 JVM 中,线程是有 9 个状态,如下所示,有兴趣的同学可以深入了解一下。

javaClasses.hpp
enum ThreadStatus {NEW = 0,RUNNABLE = JVMTI_THREAD_STATE_ALIVE + // runnable / runningJVMTI_THREAD_STATE_RUNNABLE,SLEEPING = JVMTI_THREAD_STATE_ALIVE + // Thread.sleep()JVMTI_THREAD_STATE_WAITING +JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT +JVMTI_THREAD_STATE_SLEEPING,IN_OBJECT_WAIT = JVMTI_THREAD_STATE_ALIVE + // Object.wait()JVMTI_THREAD_STATE_WAITING +JVMTI_THREAD_STATE_WAITING_INDEFINITELY +JVMTI_THREAD_STATE_IN_OBJECT_WAIT,IN_OBJECT_WAIT_TIMED = JVMTI_THREAD_STATE_ALIVE + // Object.wait(long)JVMTI_THREAD_STATE_WAITING +JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT +JVMTI_THREAD_STATE_IN_OBJECT_WAIT,PARKED = JVMTI_THREAD_STATE_ALIVE + // LockSupport.park()JVMTI_THREAD_STATE_WAITING +JVMTI_THREAD_STATE_WAITING_INDEFINITELY +JVMTI_THREAD_STATE_PARKED,PARKED_TIMED = JVMTI_THREAD_STATE_ALIVE + // LockSupport.park(long)JVMTI_THREAD_STATE_WAITING +JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT +JVMTI_THREAD_STATE_PARKED,BLOCKED_ON_MONITOR_ENTER = JVMTI_THREAD_STATE_ALIVE + // (re-)entering a synchronization blockJVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER,TERMINATED = JVMTI_THREAD_STATE_TERMINATED
};

Java 线程实现

下面讲一讲在 Java 中如何创建一个线程。众所周知,实现 Java 线程有 2 种方式:继承 Thread 类和实现 Runnable 接口。

继承 Thread 类

继承 Thread 类,重写 run() 方法。

class MyThread extends Thread {@Overridepublic void run() {System.out.println("MyThread");}}

实现 Runnable 接口

实现 Runnable 接口,实现 run() 方法。

class MyRunnable implements Runnable {public void run() {System.out.println("MyRunnable");}}

这 2 种线程的启动方式也不一样。MyThread 是一个线程类,所以可以直接 new 出一个对象出来,接着调用 start() 方法来启动线程;而 MyRunnable 只是一个普通的类,需要 new 出线程基类 Thread 对象,将 MyRunnable 对象传进去。

下面是启动线程的方式:

public class ThreadImpl {public static void main(String[] args) {MyThread myThread = new MyThread();Thread myRunnable = new Thread(new MyRunnable());System.out.println("main Thread begin");myThread.start();myRunnable.start();System.out.println("main Thread end");}}

打印结果如下:

main Thread begin
main Thread end
MyThread
MyRunnable

看这结果,不像咱们之前的串行执行依次打印,主线程不会等待子线程执行完。

敲重点:不能直接调用 run(),直接调用 run() 不会创建线程,而是主线程直接执行 run() 的内容,相当于执行普通函数。这时就是串行执行的。看下面代码:

public class ThreadImpl {public static void main(String[] args) {MyThread myThread = new MyThread();Thread myRunnable = new Thread(new MyRunnable());System.out.println("main Thread begin");myThread.run();myRunnable.run();System.out.println("main Thread end");}}

打印结果:

main Thread begin
MyThread
MyRunnable
main Thread end
从结果看出只是串行的,但看不出没有线程,我们看下面例子来验证直接调用
run() 方法没有创建新的线程,使用 VisualVM 工具来观察线程情况。我们对代码做一下
修改,加上 Thread.sleep(1000000) 让它睡眠一段时间,这样方便用工具查看线程情况。

调用 run() 的代码:

public class ThreadImpl {public static void main(String[] args) {MyThread myThread = new MyThread();myThread.setName("MyThread");Thread myRunnable = new Thread(new MyRunnable());myRunnable.setName("MyRunnable");System.out.println("main Thread begin");myThread.run();myRunnable.run();System.out.println("main Thread end");try {Thread.sleep(1000000);} catch (InterruptedException e) {e.printStackTrace();}}}class MyThread extends Thread {@Overridepublic void run() {System.out.println("MyThread");try {Thread.sleep(1000000);} catch (InterruptedException e) {e.printStackTrace();}}}class MyRunnable implements Runnable {public void run() {System.out.println("MyRunnable");try {Thread.sleep(1000000);} catch (InterruptedException e) {e.printStackTrace();}}}

运行结果:

main Thread begin
MyThread

只打印出 2 句日志,观察线程时也只看到 main 线程,没有看到 MyThread 和 MyRunnable 线程,印证了上面咱们说的:直接调用 run() 方法,没有创建线程。

下面我们来看看有调用 start() 的代码:

public class ThreadImpl {public static void main(String[] args) {MyThread myThread = new MyThread();myThread.setName("MyThread");Thread myRunnable = new Thread(new MyRunnable());myRunnable.setName("MyRunnable");System.out.println("main Thread begin");myThread.start();myRunnable.start();System.out.println("main Thread end");try {Thread.sleep(1000000);} catch (InterruptedException e) {e.printStackTrace();}}}

运行结果:

main Thread begin
main Thread end
MyThread
MyRunnable

所有日志都打印出来了,并且通过 VisualVM 工具可以看到 MyThread 和 MyRunnable 线程。看到了这个结果,切记创建线程要调用 start() 方法。


福利

扫描添加小编微信,备注“姓名+公司职位”,加入【云计算学习交流群】,和志同道合的朋友们共同打卡学习!

推荐阅读:

  • 干货分享: 服务器处理器基础知识

  • 盘点2019十大科技并购:IBM收购红帽居首,阿里考拉仅排第十;英特尔20亿美元收购Habana Labs;柳传志将卸任联想……

  • 程序员创业前要做哪些准备?

  • 倒计时 3 天 | 年前不学习,年后无加薪!区块链开发者们不要纠结了!(内含赠票福利)

  • 高通:2 亿像素手机 2020 年诞生!

  • 超模脸、网红脸、萌娃脸...换头像不重样?我开源了5款人脸生成器

真香,朕在看了!

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

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

相关文章

特征工程自动化如何为机器学习带来重大变化

随着技术的快速发展,在数据科学领域中,包括库、工具和算法等总会不断地变化的。然而,一直都有这么一个趋势,那就是自动化水平不断地提高。 近些年来,在模型的自动化选择和超参数调整方面取得了一些进展,但…

工作组访问不到别人的计算机,众果搜的博客

常见问题:A 在网上邻居列表中找不到目标计算机。B 在网上邻居列表能找到,但却访问不了。C 以UNC路径能访问,但在网上邻居列表中却找不到。1、网上邻居列表的维护依赖于浏览服务(Computer Browers),计算机通过广播方式登记到浏览器…

java 实现压缩zip的几种方案

需求,将指定目录下的文件及文件夹压缩成一个指定赔案号为名称,以".zip"结尾的压缩包提供客户下载。 package com.gblfy.util;import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.Fil…

序列模型简介——RNN, Bidirectional RNN, LSTM, GRU

既然我们已经有了前馈网络和CNN,为什么我们还需要序列模型呢?这些模型的问题在于,当给定一系列的数据时,它们表现的性能很差。序列数据的一个例子是音频的剪辑,其中包含一系列的人说过的话。另一个例子是英文句子&…

行!人工智能玩大了!程序员:太牛!你怎么看?

人工智能真的玩大了吗?人工智能行业的人才真的“爆发了?”AI程序员究竟怎么样?中国AI前景分析 程序员与远方最新参考,是12月2日出炉的《人工智能技术专利深度分析报告》。中国AI专利,已经位于世界前列,且正…

可应用于实际的14个NLP突破性研究成果(一)

语言理解对计算机来说是一个巨大的挑战。幼儿可以理解的微妙的细微差别仍然会使最强大的机器混淆。尽管深度学习等技术可以检测和复制复杂的语言模式,但机器学习模型仍然缺乏对我们的语言真正含义的基本概念性理解。 但在2018年确实产生了许多具有里程碑意义的研究…

String 常用API

public static void main(String[] args) {/*** String 常用API* 字符串* 1>截取* 2>替换**/String fileSuffix ".jpg";int i fileSuffix.indexOf(".");//截取.之后的内容,包含. indexs0String newStr fileSuffix.substring(i 0);…

小学五年级年级计算机教学计划,小学五年级信息技术教学计划范文

人类社会已进入信息时代,日新月异的信息技术在不断地改变着周围的世界。为了推广计算机信息技术,提高全民族的科学文化素质,发展小学信息技术教育。下面是学习啦小编整理的小学五年级信息技术教学计划范文,希望对大家有所帮助!小学五年级信息技术教学计划范文(一)一…

阿里资深技术专家:优秀的数据库存储引擎应具备哪些能力?

导读 本文作者是阿里巴巴OLTP数据库团队资深技术专家——曲山。作为自研高性能、低成本存储引擎X-Engine的负责人,曲山眼中的优秀关系型数据库存储引擎应该具备哪些能力呢? 正文 数据库内核按层次来分,就是两层:SQL & Stor…

开发函数计算的正确姿势——网页截图服务

前言 首先介绍下在本文出现的几个比较重要的概念: 函数计算(Function Compute): 函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传。函数计算准备计算资源&am…

java实现删除指定指定目录下面指定某种类型的文件

/*** 删除指定目录下面指定文件类型的文件** param path*/public static void delSpecifyTheTypeFile(String path) {File dir new File(path);// 该文件目录下文件全部放入数组File[] files dir.listFiles();if (files ! null) {for (int i 0; i < files.length; i) {St…

如何关闭计算机的f12功能键,win10如何关闭快捷键?win10关闭F1~F12快捷键的方法

win10如何使用快捷键关闭?在win10系统中我们按下F1~F12原本可以正常使用系统中的功能。而然在笔记本中F1~F12竟然被笔记本中的功能所替代了&#xff0c;例如&#xff1a;打开/关闭 无线网卡&#xff0c;屏幕亮度加减、系统音量大小等&#xff0c;导致我们在使用F1~F12的时候只…

阿里巴巴宣布架构调整;英伟达放大招!重磅发布 ​TensorRT 7 ,支持超千种计算变换;苹果、谷歌和亚马逊罕见结盟……...

戳蓝字“CSDN云计算”关注我们哦&#xff01; 嗨&#xff0c;大家好&#xff0c;重磅君带来的【云重磅】特别栏目&#xff0c;如期而至&#xff0c;每周五第一时间为大家带来重磅新闻。把握技术风向标&#xff0c;了解行业应用与实践&#xff0c;就交给我重磅君吧&#xff01;重…

阿里开源分布式事务解决方案 Fescar 全解析

广为人知的阿里分布式事务解决方案&#xff1a;GTS&#xff08;Global Transaction Service&#xff09;&#xff0c;已正式推出开源版本&#xff0c;取名为“Fescar”&#xff0c;希望帮助业界解决微服务架构下的分布式事务问题&#xff0c;今天我们一起来深入了解。 FESCAR o…

鲜为人知的混沌工程,到底哪里好?

混沌工程属于一门新兴的技术学科&#xff0c;行业认知和实践积累比较少&#xff0c;大多数IT团队对它的理解还没有上升到一个领域概念。阿里电商域在2010年左右开始尝试故障注入测试的工作&#xff0c;希望解决微服务架构带来的强弱依赖问题。通过本文&#xff0c;你将了解到&a…

计算机软考中集成系统,软考中级系统集成项目管理工程师有哪些作用?

系统集成项目管理工程师属于计算机技术与软件专业技术资格(水平)考试(即软考)中级资格考试里面的一项考试。对于中级工程师而言&#xff0c;通过评定获得职称证书的人比通过考试获得职称证书的人更容易被社会认可与接受。因为评定职称的人有资格、有经验&#xff1b;在当今社会…

Nutanix在中国市场发布多云合作伙伴计划

近日&#xff0c;企业云操作系统厂商Nutanix宣布&#xff0c;在中国市场正式发布“精英技术联盟合作伙伴计划”。 “精英技术联盟合作伙伴计划”面向国内解决方案、应用和软硬件合作伙伴以及开发人员&#xff0c;帮助他们在全球领先的企业云平台上构建和部署差异化的解决方案&a…

将视觉深度学习模型应用于非视觉领域

介绍 近些年来&#xff0c;深度学习技术已经彻底改变了计算机视觉领域。由于迁移学习和各种各样的学习资源的出现&#xff0c;任何人都可以通过使用预训练的模型&#xff0c;将其应用到自己的工作当中&#xff0c;以此获得非常好的结果。随着深度学习越来越商业化&#xff0c;…

字符串随机生成工具类

package com.gblfy.util;import org.springframework.stereotype.Component;import java.util.ArrayList; import java.util.Arrays; import java.util.Random;/*** 字符随机生成类*/ Component public class RandomStrUtil {/*** 随机产生类型枚举*/public static enum TYPE {…

什么是应用宝统一链接服务器,applink

从同构的角度和降级支持的角度来看&#xff0c;使用Android和iOS系统增强的AppLinks和Universal Links&#xff0c;通过HTTPS统一标准打开APP是标准的选择。使用自定义Scheme打开APP适用于&#xff1a;网站尚不支持HTTPS&#xff1b;App的iOS版本尚未添加Universal Links支持&a…