【JavaEE】多线程(二)
多线程(二)
文章目录
- 多线程(二)
- 第一个多线程程序
- 观察线程
- sleep
- 创建线程
- 继承Thread类,重写run方法
- 实现Runnable, 重写run
- 继承Thread,重写run
- 实现Runnable,重写run
- 基于lambda表达式
- Thread的常见构造方法
- Thread几个常见属性
- setDaemon();
- isAlive();
续上文, 多线程(一),我们可以了解到,多线程和普通程序的区别:
- 每一个程序都是一个独立的执行流
- 多个线程之间都是“并发”执行的
第一个多线程程序
class MyTread extends Thread{@Overridepublic void run() {//这个方法就是线程的入口方法while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("hello thread");}}
}//演示创建线程
public class Demo1 {public static void main(String[] args) throws InterruptedException {Thread t = new MyTread();//start 和 run 都是 Thread 的成员//run 只是描述了线程的入口(线程主要做什么任务)//start 则是真正调用了系统API,在系统中创建线程,让线程再调用run//t.start();//t.run();t.start();while (true){System.out.println("hello main");Thread.sleep(1000);}}
}
通过运行这个程序,我们可以发现两个while
循环在“同时执行”,可以看到打印结果是两边的日志在交替打印的:
这也说明了:
每个线程都是一个独立执行的逻辑,也就是独立的执行流~
我们也可以形象的看作是:兵分两路,并发执行~
而 并发 => 并行 + 并发
=> 并发编程的效果 => 充分使用多核cpu
资源
不过当我们将main
函数的t.start();改成t.run();
public static void main(String[] args) throws InterruptedException {Thread t = new MyTread();//start 和 run 都是 Thread 的成员//run 只是描述了线程的入口(线程主要做什么任务)//start 则是真正调用了系统API,在系统中创建线程,让线程再调用runt.run();while (true){System.out.println("hello main");Thread.sleep(1000);}}
此时,代码中不会创建新的线程,就只有一个主线程,这个主线程只能依次执行循环,执行完一个在执行另外一个~,不过因为代码中是while(true)
,是不会循环结束的,所以代码也就无法走到hello main
了。
还有一个需要我们了解的:main
这个线程是jvm
自动创建的,和其他线程比起来并没有什么特殊的,在一个java
进程中,至少都会有一个main
线程。
观察线程
当我们多线程程序运行的时候,我们可以使用IDEA
或者jconsole
来观察该进程内的多线程情况~
这里我们主要介绍jconsole
,jconsole
是jdk
自带的程序
而jconsole
我们可以在jdk
包里找到
-
首先我们要先找到
jdk
的安装地址 -
在地址处找到
jdk
然后打开bin
目录,然后再列表中找到jconsole.exe
这里我们要注意的是:
- 在启动
jconsole.exe
之前,我们得确保IDEA
的程序已经跑起来了
sleep
上述的线程,我觉得他在while
循环中转的太快了,想要他慢点~
那我们就可以使用Thread.sleep();
,sleep
是Thread
的静态方法
需要注意的是:我们使用sleep
的时候汇报这样的错误
MyRunnable
里的异常是受查异常,必须要显示处理,此处必须try catch
,不能用throws
,在这个代码中是重写父类的run
,父类的run
没有throws
,子类方法也就不能也有。
而这个程序每秒所打印出来的内容,顺序都是不确定的。
因为这两线程都是休眠1000ms
,当时间到后,谁先谁后是不一定的,这个过程可以视为“随机”
操作系统,对于多个线程的调度顺序,是不确定,随机的,而此处的随机不是数学上的概率均等的随机,是取决于 操作系统 对于线程调度的模块(调度器)来具体实现的~
创建线程
继承Thread类,重写run方法
package Thread.test_8_12;
class MyTread extends Thread{@Overridepublic void run() {//这个方法就是线程的入口方法while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("hello thread");}}
}//演示创建线程
public class Demo1 {public static void main(String[] args) throws InterruptedException {Thread t = new MyTread();//start 和 run 都是 Thread 的成员//run 只是描述了线程的入口(线程主要做什么任务)//start 则是真正调用了系统API,在系统中创建线程,让线程再调用run//t.start();//t.run();t.start();while (true){System.out.println("hello main");Thread.sleep(1000);}}
}
实现Runnable, 重写run
package Thread.test_8_12;
class MyRunnable implements Runnable{@Overridepublic void run() {while (true) {System.out.println("hello world");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}public class Demo2 {public static void main(String[] args) throws InterruptedException {Runnable runnable = new MyRunnable();Thread t = new Thread(runnable);t.start();while (true){System.out.println("hello main");Thread.sleep(1000);}}
}
好处:
使用Runnable
的写法,和直接继承Thread
之间的区别就是:解耦合
使用Runnable
接口重写run
方法相对于直接继承Thread
类的方式更加灵活、可扩展,并且能够实现解耦合。我们可以将任务逻辑与线程的实现分离,通过实现Runnable
接口,我们能够更好地控制线程的行为并在需要时更好地管理和复用线程。
这里我们举个例子:
你老婆想要喝水,但是她又懒得去接水,于是她就会叫你或者你5岁孩子去接水。
而接水就是一个任务,你执行还是你孩子执行,这是没有本质区别的,那么此时我们就可以将接水这个任务单独提取为Runnable
,后续是谁都可以轻轻松松完成这个任务~
但是如果任务变了呢?接水 -> 泡茶
那么此时这个任务就只能你来完成了,你那5岁孩子完成不来任务
那么这个任务就是和你这个线程有一定耦合关系的~
而我们创建一个线程,需要进行两个关键操作:
-
明确线程要执行的任务
任务本身,不一定和线程 概念 强相关的
- 这个任务只是单纯的执行一段代码,这个任务是使用单个线程执行还是多个线程执行,亦或是别的方式(信号处理函数/协程/线程池)都没什么区别~
- 任务本身,就可以将任务本身提取出来,此时就可随时把代码改成使用其他方式来执行这个任务~
-
调用系统的
api
创建线程
继承Thread,重写run
package Thread.test_8_12;
public class Demo3 {public static void main(String[] args) {//匿名内部类Thread t = new Thread(){@Overridepublic void run() {while (true){System.out.println("hello world");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};t.start();while (true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
**
**
实现Runnable,重写run
package Thread.test_8_12;
public class Demo4 {public static void main(String[] args) {Runnable runnable = new Runnable() {@Overridepublic void run() {while (true) {System.out.println("hello world");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};Thread t = new Thread(runnable);t.start();while (true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
基于lambda表达式
package Thread.test_8_12;
public class Demo6 {public static void main(String[] args) {Thread t = new Thread(()->{while (true){System.out.println("hello world");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();while (true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
那为什么lambda
表达式不用重写run
方法?
实际上啊,lambda
自身就是run
方法
lambda
:本身就是用来表示逻辑的,使用lambda
就能描述出当前的线程要干嘛run
方法:线程的入口,通俗来说就是:告诉线程你要干啥子~
Thread的常见构造方法
方法 | 说明 |
---|---|
Thread() | 创建线程对象 |
Thread(Runnable target) | 使用Runnable对象创建线程对象 |
Thread(String name) | 创建线程对象,并命名 |
Thread(Runnable target, String name) | 使用Runnable对象创建线程对象,并命名 |
Thread(TreadGroup group, Runnable target) | 线程可以被用来分组管理,分好的几位线程组 |
public class Demo7 {public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}, "这是一个新线程");t.start();}
Thread几个常见属性
属性 | 获取方法 |
---|---|
ID | getId() |
名称 | getName() |
状态 | getState() |
优先级 | getPriority() |
是否后台进程 | isDaemon() |
是否存活 | isAlive() |
是否被中断 | isInterrupted() |
setDaemon();
一般默认下,一个进程是前台线程~
public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}, "这是一个新线程");//设置 t 为后台线程t.setDaemon(true);t.start();}
调用setDaemon(true)
方法,将t设置为后台线程。后台线程是一种特殊的线程,当所有前台线程(例如主线程)都结束时,后台线程会自动终止
改成后台线程之后,主线程飞快执行完了,此时就没有其他前台线程了,于是线程结束,t
线程来不及执行,就 over 了~~
isAlive();
Thread
对象的生命周期,要比系统内核中的线程更长一些~
Thread
对象还在,内核中的线程已经销毁了这样的情况(不求同年同月同日生,也不求i同年同月同日死)
所以我们可以使用isAlive();
来判定内核线程是不是已经没了,也就是回调函数执行完毕,线程就没了
package Thread;
public class Demo8 {public static void main(String[] args) {Thread t = new Thread(()->{System.out.println("线程开始");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程结束");});t.start();System.out.println(t.isAlive());try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(t.isAlive());}
}
下面用一张图概括一下本篇文章所讲的内容~
至此,多线程(二)先写到这,后续会持续更新,敬请期待~
相关文章:
【JavaEE】多线程(二)
多线程(二) 文章目录 多线程(二)第一个多线程程序观察线程sleep创建线程继承Thread类,重写run方法实现Runnable, 重写run继承Thread,重写run实现Runnable,重写run基于lambda表达式 T…...
OkHttp 根据服务器返回的的过期时间设置缓存
据返回的缓存时间来缓存响应,可以通过使用OkHttp的CacheControl和ResponseCacheInterceptor来实现。以下是一个示例代码: // 创建缓存目录和缓存对象 File cacheDirectory new File(context.getCacheDir(), "http-cache"); int cacheSize 1…...
智能远程监考方案助力企业考试化繁为简
在音视频数字化之旅中,轻装上阵。 近年来,在数字化浪潮之下,远程考试频繁成为各领域热词,各企业也纷纷改革求新,将原本的企业内部考试转移到线上,从而获取更低廉的组考成本,更高的管理效率&…...
基于matlab实现的额 BP神经网络电力系统短期负荷预测未来(对比+误差)完整程序分享
基于matlab实现的额 BP神经网络电力系统短期负荷预测 完整程序: clear; clc; %%输入矢量P(15*10) P[0.2452 0.1466 0.1314 0.2243 0.5523 0.6642 0.7105 0.6981 0.6821 0.6945 0.7549 0.8215 0.2415 0.3027 0; 0.2217 0.1581 0.1408 0.23…...
WPF的_Expander控件
WPF Expander 是 WPF(Windows Presentation Foundation)框架中的一个控件,用于实现可以展开和折叠内容的可折叠面板。 Expander 控件通常由一个展开/折叠的标题(Header)和一个显示/隐藏的内容部分(Content…...
【MT7628AN】IOT | MT7628AN OpenWRT开发与学习
IOT | MT7628AN OpenWRT开发与学习 时间:2023-06-21 文章目录 `IOT` | `MT7628AN` `OpenWRT`[开发与学习](https://blog.csdn.net/I_feige/article/details/132911634?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22132911634…...
基于Matlab实现自动泊车(垂直泊车)
自动泊车是一项非常有趣和实用的技术,它可以让车辆在没有人为干预的情况下自动停放在合适的位置上。在这篇文章中,我们将介绍如何使用Matlab实现自动泊车。 首先,我们需要了解自动泊车的基本原理。自动泊车系统通常包括车辆、传感器和控制算…...
笔试面试相关记录(4)
(1)实现防火墙的主流技术有哪些? 实施防火墙主要采用哪些技术 - 服务器 - 亿速云 (yisu.com) (2) char arr[][2] {a, b, c, d}; printf("%d", *(arr1)); 输出的是谁的地址?字符c 测试代码如下…...
unity UDP 通信
客户端 接收端 : using System; using System.IO; using System.Collections; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using UnityEngine; using UnityEngine.UI;public cla…...
一篇解决JavaScript
华子目录 JavaScript介绍JavaScript的组成JavaScript书写位置内部外部 js注释js输入(prompt)js输出js变量js基本数据类型number(数值类型)string(字符串)Boolean(布尔类型)undefined…...
Unity UGUI(一)基础组件
文章目录 1.Text:文本框2.Image:精灵图3.RawImage:生图4.Button:按钮5.InputField:输入框6.Tooggle:选择框7.Slider:滑动条8.Dropdown:下拉菜单9.Scrollbar:滚动条10.Scr…...
【微服务】六. Nacos配置管理
6.1 Nacos实现配置管理 配置更改热更新 在nacos左侧新建配置管理 Data ID:就是配置文件名称 一般命名规则:服务名称-环境名称.yaml 配置内容填写:需要热更新需求的配置 配置文件的id:[服务名称]-[profile].[后缀名] 分组&#…...
【华为云云耀云服务器L实例评测|云原生】自定制轻量化表单Docker快速部署云耀云服务器
🤵♂️ 个人主页: AI_magician 📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。 👨💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!&…...
无涯教程-JavaScript - ACOTH函数
描述 ACOTH函数返回数字的反双曲余切。 语法 ACOTH (number)争论 Argument描述Required/OptionalNumberThe absolute value of Number must be greater than 1. i.e., Number must be must be less than -1 or greater than 1.Required Notes 用于计算双曲反余切的方程为-…...
Qt QTreeWidge解决setItemWidget后,导致复选框失效
一、问题: QTreeWidget某一项加上itemWidget后,导致复选框失效问题 二、解决方法 将要加上的widget控件加到该项的后续的列,即控件跟复选框不同一列 三、具体代码 QTreeWidget* treeW new QTreeWidget; treeW->setColumnCount(2); /…...
strncpy
strncpy: 函数介绍: 函数原型: char *strncpy(char *dest, const char *src, int n) 返回值:dest字符串起始地址 说明: 1、当src字符串长度小于n时,则拷贝完字符串后,剩余部分将用空字节填…...
c++学习【23】matlab实现FOC算法
% 创建Figure窗口和滑块 figure;Id_slider uicontrol(Style, slider, Position, [100 50 120 20], ...Min, -5, Max, 5, Value, 1.5, Callback, updateVoltage); Id_text uicontrol(Style, text, Position, [100 80 120 20], String, d轴电流: 1.5);Iq_slider uicontrol(Sty…...
2020-2023中国高等级自动驾驶产业发展趋势研究-概念界定
1.1 概念界定 自动驾驶发展过程中,中国出现了诸多专注于研发L3级以上自动驾驶的公司,其在业界地位也越来越重要。本报告围绕“高等级自动驾驶” 展开,并聚焦于该技术2020-2023年在中国市场的变化趋势进行研究。 1.1.1 什么是自动驾驶 自动驾驶…...
ICPC 2022 网络赛 h (模拟
#include<bits/stdc.h> using namespace std; using VI vector<int>; using ll long long; const int mod 20220911;//枚举数位,枚举这一位余数是几 //每一位的限制, //如果有repeat 就下一个 int change(string x){int res 0 ;for(int …...
如何保护您的工业网络?
工业网络通过连接机器、设备和系统,在实现工业流程的高效生产、监控和管理方面发挥着关键作用。保护工业网络,确保其关键资产和流程的完整性、可用性和机密性,是工业组织的首要任务。在本文中,我们将探讨保护工业网络安全面临的障…...
Python之设计模式
一、设计模式_工厂模式实现 设计模式是面向对象语言特有的内容,是我们在面临某一类问题时候固定的做法,设计模式有很多种,比较流行的是:GOF(Goup Of Four)23种设计模式。当然,我们没有必要全部学…...
redis 多租户隔离 ACL 权限控制(redis-cli / nodejs的ioredis )
Redis 6版本之后:提供ACL的功能对用户进行更细粒度的权限控制 :(1)接入权限:用户名和密码(2)可以执行的命令(3)可以操作的 KEY ACL常用规则介绍: 指令列表 //增加可操…...
【算法专题突破】滑动窗口 - 找到字符串中所有字母异位词(14)
目录 1. 题目解析 2. 算法原理 3. 代码编写 写在最后: 1. 题目解析 题目链接:438. 找到字符串中所有字母异位词 - 力扣(Leetcode) 这道题很好理解,就是找出从不同位置开始的所有异位词。 2. 算法原理 那我们该如…...
C++生成-1到1的随机数
目录 一、方法一1、主要函数2、示例代码 二、方法二1、方法概述2、参考文献3、示例代码 三、方法三1、参考链接2、示例代码 本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、方法一 1、主要函数…...
React-Hooks 和 React-Redux
注:Redux最新用法参考 个人React专栏 react 初级学习 Hooks基本介绍------------------------- Hooks:钩子、钓钩、钩住, Hook 就是一个特殊的函数,让你在函数组件中获取状态等 React 特性 ,是 React v16.8 中的新增功…...
虚拟机下载与Ubuntu安装
下载VMware 进入官网资源 -> 产品下载 -> Desktop & End-User Computing选择 VMware Workstation Pro 这一栏,点击右边的下载产品,跳到新页面选择版本(我选的是 16.0),然后点击下面对应系统的转至下载&…...
【小数点】C#使用Math.Round方法保留指定小数点位数,并且整数也同样保持统一的2位
2023年,第38周。给自己一个目标,然后坚持总会有收货,不信你试试! 在实际开发项目中,特别是涉及金额之类的字段,一般都会用到小数,有些是保留1、2、3小数点。 本篇文章主要简单讲讲,如…...
Android多种方法获取系统属性
这里使用获取rga版本为例 1,使用sh脚本方法 sh的编写 echo $(getprop vendor.rga_api.version) 其中,vendor.rga_api.version是关键字 相关方法也有两种,一种是从sh脚本读取流,一种是指令很少的,直接读取字符串化…...
密码学【一】
前言 在区块链的整个体系中大量使用了密码学算法,比如用于 PoW 的哈希算法,用于完整性验证的 Merkle Tree,用于交易签名与验证的数字签名算法,用于隐私保护的零知识证明等等。 可以说密码学是保证区块链安全的基石,而区…...
企业如何选择舆情优化处置公司?
随着互联网的发展成熟,网络上的信息量已经非常之巨大,网络上的海量信息有对企业有利的,其实也有一些企业经营不利的,让不利的信息下沉,让有利的信息排上搜索首页,这就是舆情优化的简单表述。 对于大中型企业…...
批量替换wordpress文章中的文字/国内seo服务商
*** __asm void MSR_MSP(u32 addr) //__asm 关键字用于调用内联汇编程序,用来声明一个C语言函数的话, // 代表这个函数内都是汇编语句 { MSR MSP, r0 …...
网站关键词代码怎么做/成人营销管理培训班
Android应用程序均用Java开发,通过google的指导下,实现并总结了apk文件反编译过程,不难,需要相应的工具即可。 一、Apk反编译得到Java源代码 下载上述反编译工具包,打开apk2java目录下的dex2jar-0.0.9.9文件夹…...
手机网站代理/长沙百度搜索排名优化
以下是我收集的Java编程里各种区别,供Java学习爱好者参考,这些区别都是每次Java面试中常考的,大家好好掌握,如有失误请留言指出。想要获取Java详细全套学习资料请到上海尚学堂官网获取。 1、HashMap和Hashtable的区别。 HashMap是…...
网站怎么做数据分析/搜索引擎排名2020
python 中 setattr() 函数 和 getarrr() 函数...
校园网站怎么做/新闻头条新闻
Pausing Coyote HTTP/1.1 on http-8080 tomcat启动出现这个错误的时候。 其实找到占用8080端口的进程 然后干掉他,重新启动tomcat就OK了!...
知名外贸网站建设公司/网站快速上排名方法
一个电子商务网站,是依据某中盈利目的而建立。任何网站,建立后要做的第一件事情即是将网站推广出去,为人所知。通常采用的办法,一是开展线下推广,二是开展线上推广。 线下推广,一般是采取传统市场营销采用的…...