深入浅出Java的多线程编程——第一篇

目录

1. 认识线程(Thread)

1.1 概念

1.1.1 线程是什么

1.1.2 为啥需要线程

1.1.3 进程和线程的区别

1.1.4 Java的线程和操作系统线程的关系

1.2 第一个多线程程序

1.3 创建线程的方式(5种)

1.3.1 继承Thread类

1.3.2 实现Runnable接口

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

1.3.4 实现Runnable接口,使用匿名内部类

1.3.5 使用lambda表达式创建线程(推荐)

1.4 多线程的优势—增加运行速度

2. Thread类及常见方法

2.1 Thread的常见构造方法

2.2 Thread的几个常见属性


前情回顾:操作系统、进程和线程_木子斤欠木同的博客-CSDN博客

1. 认识线程(Thread)

1.1 概念

1.1.1 线程是什么

一个线程就是一个 "执行流". 每个线程之间都可以按照顺讯执行自己的代码 . 多个线程之间 " 同时 " 执行着多份代码.
举个栗子:
我们设想如下场景:
       一家公司要去银行办理业务,既要进行财务转账,又要进行福利发放,还得进行缴社保。
       如果只有张三一个会计就会忙不过来,耗费的时间特别长。为了让业务更快的办理好,张三又找 来两位同事李四、王五一起来帮助他,三个人分别负责一个事情,分别申请一个号码进行排队, 自此就有了三个执行流共同完成任务,但本质上他们都是为了办理一家公司的业务。
       此时,我们就把这种情况称为多线程,将一个大任务分解成不同小任务,交给不同执行流就分别 排队执行。其中李四、王五都是张三叫来的,所以张三一般被称为主线程(Main Thread)。 

1.1.2 为啥需要线程

首先, "并发编程" 成为 "刚需"。
  • 单核 CPU 的发展遇到了瓶颈. 要想提高算力, 就需要多核 CPU. 而并发编程能更充分利用多核 CPU资源.
  • 有些任务场景需要 "等待 IO", 为了让等待 IO 的时间能够去做一些其他的工作, 也需要用到并发编.

其次, 虽然多进程也能实现 并发编程, 但是线程比进程更轻量.

  • 创建线程比创建进程更快.
  • 销毁线程比销毁进程更快.
  • 调度线程比调度进程更快.
最后, 线程虽然比进程轻量, 但是人们还不满足, 于是又有了 "线程池"(ThreadPool) 和 "协程"
(Coroutine)

1.1.3 进程和线程的区别

  • 进程是包含线程的. 每个进程至少有一个线程存在,即主线程。
  • 进程和进程之间不共享内存空间. 同一个进程的线程之间共享同一个内存空间.

多进程就是例如同时打开QQ音乐和微信,他们连各自为一个进程。
多线程就是例如打开微信的聊天功能和朋友圈,他们各自为一个线程。
进程是资源分配的基本单位!
线程共享同一份资源!
  • 进程是系统分配资源的最小单位,线程是系统调度的最小单位。

1.1.4 Java的线程和操作系统线程的关系

线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 并且对用户层提供了一些 API 供用户使用(例如 Linux 的 pthread 库)

Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进行了进一步的抽象和封装

注:也就是说Java的线程和操作系统的线程是两回事,能思想线程的功能是操作系统内核
 

1.2 第一个多线程程序

感受多线程程序和普通程序的区别:

  • 每个线程都是一个独立的执行流
  • 多个线程之间是 "并发" 执行的
class MyThread extends Thread{@Overridepublic void run(){while(true){System.out.println("hello t");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}public class Test {public static void main(String[] args) {MyThread myThread = new MyThread();myThread.start();while(true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

使用jconsole命令观察线程

这是jdk提供的工具,能够让我们查看java进程里面线程的详情!

jconsole只能分析java进程,不能识别非java写的进程~~

除了main和Thread-0两个线程之外,剩下都是JVM自己创建的!

1.3 创建线程的方式(5种)

1.3.1 继承Thread类

class MyThread extends Thread{@Overridepublic void run(){while(true){System.out.println("hello t");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}public class Test {public static void main(String[] args) {MyThread myThread = new MyThread();myThread.start();while(true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

1.3.2 实现Runnable接口

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

注:以上两种创建线程的区别在于,实现Runnable接口的方法使线程和线程要做的事情分开了,达到了解耦合的作用

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

    public static void main(String[] args) {Thread t1 = new Thread(){@Overridepublic void run(){System.out.println("hello");}};}

1.3.4 实现Runnable接口,使用匿名内部类

    public static void main(String[] args) {Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("hello");}});}

1.3.5 使用lambda表达式创建线程(推荐)

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

1.4 多线程的优势—增加运行速度

可以观察多线程在一些场合是可以提高程序整体运行的效率

  • 使用 System.currentTimeMillis()可以记录当前系统的 纳秒 级时间戳.

(1)串行

    public static void main(String[] args) {long start = System.currentTimeMillis();for(int a = 0;a < 1000;a++){try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}}for(int b = 0;b < 1000;b++){try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}}long end = System.currentTimeMillis();System.out.println(end - start);}

(2)并发

    public static void main(String[] args) {Thread t = new Thread(()->{for(int a = 0;a < 1000;a++){try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}}});long start = System.currentTimeMillis();t.start();for(int b = 0;b < 1000;b++){try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}}long end = System.currentTimeMillis();System.out.println(end - start);}

 

2. Thread类及常见方法

Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联。

用我们上面的例子来看,每个执行流,也需要有一个对象来描述,类似下图所示,而 Thread 类的对象,就是用来描述一个线程执行流的,JVM 会将这些 Thread 对象组织起来,用于线程调度,线程管理。

2.1 Thread的常见构造方法

方法说明
Thread()创建线程对象
Thread(Runnable target)使用Runnable对象创建线程对象
Thread(String name)创建下线程对象,并命名
Thread(Runnable target,String name)使用Runnable对象创建线程对象,并命名
【了解】Thread(ThreadGroup group,Runnable target)线程可以被用来分组管理,分好的组即为线程组,这个目前我们了解即可

2.2 Thread的几个常见属性

属性获取方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否后台进程isDaemon()
是否存活isAlive()
是否被中断isInterrupted()
  • ID 是线程的唯一标识,不同线程不会重复
  • 名称是各种调试工具用到
  • 状态表示线程当前所处的一个情况,下面我们会进一步说明
  • 优先级高的线程理论上来说更容易被调度到
  • 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。
  • 是否存活,即简单的理解,为 run 方法是否运行结束了
  • 线程的中断问题,下面我们进一步说明
     

特别说明:isDaemon()方法

true表示是后台线程

false表示是前台进程

(1)后台进程不阻止Java进程结束。哪怕后台线程还没有执行完,Java进程该结束就结束了。

(2)前台线程会阻止Java进程结束,必须得java进程中所有的前台线程都执行完,Java进程才会结束。

(3)创建的线程默认都是前台的,可以通过setDaemon()方法设置为后台。

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

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

相关文章

AVL树的模拟实现(c++)

目录 搜索二叉树对于搜索查询来说是非常快的&#xff0c;但是它有着致命的缺陷&#xff0c;如果插入的数据是有序的&#xff0c;那么它的结构就会变成单链表&#xff0c;这对于搜索查询来说是非常不利的&#xff0c;因此为了解决搜索树的缺陷&#xff0c;弥补它的不足&#xff…

网络编程-UDP协议(发送数据和接收数据)

需要了解TCP协议的&#xff0c;可以看往期文章 https://blog.csdn.net/weixin_43860634/article/details/133274701 TCP/IP参考模型 通过此图&#xff0c;可以了解UDP所在哪一层级中 代码案例 发送数据 package com.hidata.devops.paas.udp;import java.io.IOException; …

海康、大华等IPC解码上墙,PC上平台同时查看方案

【金山文档】 wvp-gb28181-prohttps://kdocs.cn/l/cneSpcss6bo2

多层感知机——MLP

源代码在此处&#xff1a;https://github.com/wepe/MachineLearning/tree/master/DeepLearning Tutorials/mlp 一、多层感知机&#xff08;MLP&#xff09;原理简介 多层感知机&#xff08;MLP&#xff0c;Multilayer Perceptron&#xff09;也叫人工神经网络&#xff08;ANN&…

孜然单授权系统V1.0[免费使用]

您还在为授权系统用哪家而发愁&#xff1f;孜然单授权系统为您解决苦恼&#xff0c;本系统永久免费。 是的&#xff0c;还是那个孜然&#xff0c;消失了一年不是跑路了是没有空&#xff0c;但是这些都是无关紧要的&#xff0c;为大家带来的孜然单授权系统至上我最高的诚意&…

AnyDesk多ID集中控制台V2.0

网盘下载 AnyDesk多ID集中控制台V2.0 软件介绍&#xff1a; 首先大家要知道AnyDesk软件是干嘛的&#xff1f;国外的远程协助工具&#xff0c;和TeamViewer同一个软件&#xff0c;TeamViewer确定需要登录&#xff0c;使用限制5分钟等等缺点&#xff0c;所以自己就用易语言开发An…

ElasticSearch - DSL查询文档语法,以及深度分页问题、解决方案

目录 一、DSL 查询文档语法 前言 1.1、DSL Query 基本语法 1.2、全文检索查询 1.2.1、match 查询 1.2.2、multi_match 1.3、精确查询 1.3.1、term 查询 1.3.2、range 查询 1.4、地理查询 1.4.1、geo_bounding_box 1.4.2、geo_distance 1.5、复合查询 1.5.1、相关…

关键点检测 HRNet网络详解笔记

关键点检测 HRNet网络详解笔记 0、COCO数据集百度云下载地址1、背景介绍2、HRNet网络结构3、预测结果&#xff08;heatmap&#xff09;的可视化3、COCO数据集中标注的17个关键点4、损失的计算5、评价准则6、数据增强7、模型训练 论文名称&#xff1a; Deep High-Resolution Rep…

Learn Prompt- Midjourney案例:网页设计

快速开始​ 用 “ web design for...” 或 “ modern web design for..” 来快速开始你的提示。 web design for a generic SaaS startup --ar 3:2否定提示-no​ 使用--no告诉 Midjourney 你不想要什么。Midjourney 的默认风格倾向于现实和详细。但这可能不适用于所有品牌。…

AI聊天ChatGPT系统源码卡密验证开源版

ChatGPT卡密验证版源码是一个基于PHP7.4和MySQL5.6的聊天AI源码&#xff0c;它不仅支持暗黑模式、反应速度极快&#xff0c;而且充值方面采用后台生成卡密方式&#xff0c;方便快捷&#xff0c;如果您有能力将其接入在线支付&#xff0c;即可进一步拓展充值方式&#xff0c;为更…

白帽学苑-内网渗测靶机训练(1)

本文对应靶机地址&#xff1a; BoredHackerBlog: Social Network ~ VulnHub 涉及知识点&#xff1a; 主机发现端口扫描服务发现路径爬取代码注入Shell脚本内网信息收集内网穿透漏洞利用密码破解本地提权攻击代码修改 将靶机导入虚拟机中&#xff0c;桥接模式&#xff0c;直接…

基于springboot会员制医疗预约服务管理信息系统springboot017

大家好✌&#xff01;我是CZ淡陌。一名专注以理论为基础实战为主的技术博主&#xff0c;将再这里为大家分享优质的实战项目&#xff0c;本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路…

Mysql编译安装和yum安装

一、msql数据库介绍 1、什么是sql sql代表结构化查询语言&#xff0c;sql是用于访问数据库的标椎化语言 sql包含三个部分 DDL数据定义语言包含定义数据库及其对象的语言&#xff0c;例如表&#xff0c;视图&#xff0c;触发器&#xff0c;存储过程等 DML数据操作语言包含允许数…

pytorch迁移学习训练图像分类

pytorch迁移学习训练图像分类 一、环境配置二、迁移学习关键代码三、完整代码四、结果对比 代码和图片等资源均来源于哔哩哔哩up主&#xff1a;同济子豪兄 讲解视频&#xff1a;Pytorch迁移学习训练自己的图像分类模型 一、环境配置 1&#xff0c;安装所需的包 pip install …

【深度学习实验】卷积神经网络(一):卷积运算及其Pytorch实现(一维卷积:窄卷积、宽卷积、等宽卷积;二维卷积)

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 1. 一维卷积 a. 概念 b. 示例 c. 分类 窄卷积&#xff08;Narrow Convolution&#xff09; 宽卷积&#xff08;Wide Convolution&#xff09; 等宽卷积&#xff08;Same Convolution&am…

Python开发与应用实验2 | Python基础语法应用

*本文是博主对学校专业课Python各种实验的再整理与详解&#xff0c;除了代码部分和解析部分&#xff0c;一些题目还增加了拓展部分&#xff08;⭐&#xff09;。拓展部分不是实验报告中原有的内容&#xff0c;而是博主本人自己的补充&#xff0c;以方便大家额外学习、参考。 &a…

Python3 如何实现 websocket 服务?

Python 实现 websocket 服务很简单&#xff0c;有很多的三方包可以用&#xff0c;我从网上大概找到三种常用的包&#xff1a;websocket、websockets、Flask-Sockets。 但这些包很多都“年久失修”&#xff0c; 比如 websocket 在 2010 年就不维护了。 而 Flask-Sockets 也在 2…

通信协议:Uart的Verilog实现(上)

1、前言 调制解调器是主机/设备与串行数据通路之间的接口&#xff0c;以串行单比特格式发送和接收数据。它也被称为通用异步收发器(Uart, Universal Asynchronous Receiver/Transmitter)&#xff0c;这表明该设备能够接收和发送数据&#xff0c;并且发送和接收单元不同步。 本节…

递归算法讲解,深度理解递归

首先最重要的就是要说明递归思想的作用&#xff0c;在后面学习的高级数据接口&#xff0c;树和图中&#xff0c;都需要用到递归&#xff0c;即深度优先搜索&#xff0c;如果递归掌握的不好&#xff0c;后面的数据结构将举步为艰。 加油 首先看下如何下面两个方法有什么区别&a…

git revert 撤销之前的提交

git revert 用来撤销之前的提交&#xff0c;它会生成一个新的 commit id 。 输入 git revert --help 可以看到帮忙信息。 git revert commitID 不编辑新的 commit 说明 git log 找到需要撤销的 commitID &#xff0c; 然后执行 git revert commitID &#xff0c;会提示如下…