Java底层分析多线程行为-程序员宅基地

技术标签: 程序员  java  开发语言  

}

非守护进程vs守护进程线程

在执行方面,有两种类型的线程:

  • 执行非守护程序线程会一直到结束。主线程本身就是非守护程序线程的一个很好的例子。main()除非System.exit()强制程序完成,否则代码输入将始终执行到最后。
  • 一个守护线程是相反的,是一个不需要一直执行到结束的处理程序。

请记住规则:如果封闭的非守护程序线程在守护程序线程之前结束,则守护程序线程将在结束之前执行。为了更好地理解守护进程和非守护进程线程的关系,请参考以下示例:

import java.util.stream.IntStream;

public class NonDaemonAndDaemonThread {

public static void main(String… nonDaemonAndDaemon) throws InterruptedException {
System.out.println("Starting the execution in the Thread " + Thread.currentThread().getName());

Thread daemonThread = new Thread(() -> IntStream.rangeClosed(1, 100000)
.forEach(System.out::println));

daemonThread.setDaemon(true);
daemonThread.start();

Thread.sleep(10);

System.out.println("End of the execution in the Thread " +
Thread.currentThread().getName());
}

}

在这个例子中,我使用了守护程序线程来声明1到100,000的范围,迭代所有这些,然后打印。但请记住,如果非守护进程的主线程首先完成,守护程序线程将无法完成执行。

输出将按如下方式进行:

  1. 在主线程中开始执行。
  2. 打印数字从1到100,000。
  3. 主线程中的执行结束,很可能在迭代到100,000之前完成。

最终输出将取决于你的JVM实现。

事实证明:线程是不可预测的。

线程优先级和JVM

可以使用该setPriority方法确定线程执行的优先级,但是如何处理它取决于JVM实现。Linux,MacOS和Windows都有不同的JVM实现,每个都将根据自己的默认值处理线程优先级。

但是,你设置的线程优先级确实会影响线程调用的顺序。在Thread类上的三个常数是:

/**

  • The minimum priority that a thread can have.
    */
    public static final int MIN_PRIORITY = 1;

/**

  • The default priority that is assigned to a thread.
    */
    public static final int NORM_PRIORITY = 5;

/**

  • The maximum priority that a thread can have.
    */
    public static final int MAX_PRIORITY = 10;

尝试对以下代码运行一些测试,以查看最终的执行优先级

public class ThreadPriority {

public static void main(String… threadPriority) {
Thread moeThread = new Thread(() -> System.out.println(“Moe”));
Thread barneyThread = new Thread(() -> System.out.println(“Barney”));
Thread homerThread = new Thread(() -> System.out.println(“Homer”));

moeThread.setPriority(Thread.MAX_PRIORITY);
barneyThread.setPriority(Thread.NORM_PRIORITY);
homerThread.setPriority(Thread.MIN_PRIORITY);

homerThread.start();
barneyThread.start();
moeThread.start();
}

}

即使我们设置moeThread为MAX_PRIORITY,我们也不能指望首先执行此线程。相反,执行顺序将是随机的。

但是,使用常量有一个问题:如果传递的优先级数字不在1到10的范围内,setPriority()方法将引发IllegalArgumentException。所以我们可以使用枚举来解决这个问题。使用枚举Enums既简化了代码,又能够更好地控制代码的执行。

Java线程挑战!

我们已经了解了不少关于线程的知识,如果你想更进一步,研究以下代码:

public class ThreadChallenge {
private static int line = 10;

public static void main(String… doYourBest) {
new tool(“Car”).start();

tool Bike = new tool(“Bike”);
Bike.setPriority(Thread.MAX_PRIORITY);
Bike.setDaemon(false);
Bike.start();

tool Train = new tool(“Train”);
Train.setPriority(Thread.MIN_PRIORITY);
Train.start();
}

static class tool extends Thread {
tool(String Name) { super(Name); }

@Override public void run() {
line++;
if (line == 13) {
System.out.println(this.getName());
}
}
}
}

这段代码的输出是什么?根据你上面学的内容分析代码。

A. Car
B. Bike
C. Train
D. 不确定

解析上述代码,了解多线程的运行

在上面的代码中,我们创建了三个线程。第一个线程是Car,我们为此线程分配了默认优先级。第二个线程是Bike,分配了分配了MAX_PRIORITY优先级。第二个线程是Train,分配了MIN_PRIORITY优先级。然后我们开始了多线程。为了确定线程将运行的顺序,您可能首先注意到tool类扩展了Thread类,并且我们已经在构造函数中传递了线程名称。我们还run()中如果line等于13就进行打印。注意!即使Train是我们执行顺序中的第三个线程,并且MIN_PRIORITY不能保证它将在所有JVM实现的最后执行。您可能还会注意到,在此示例中,我们将Bike线程设置为守护,所以它是一个守护程序线程,Bike可能永远不会完成执行。但是其他两个线程默认是非守护进程,因此Car和Train线程肯定会完成它们的执行。总之,结果将是D:不确定,因为无法保证线程调度程序将遵循我们的执行顺序或线程优先级。请记住,如果不借助JUC的工具,我们不能依赖程序逻辑(线程或线程优先级的顺序)来预测线程的执行顺序。

多线程常见错误

  • 调用run()方法以尝试启动新线程。
  • 试图启动一个线程两次(这将导致一个IllegalThreadStateException)。
  • 允许多个进程在不应更改时更改对象的状态。
  • 编写依赖于线程优先级的程序逻辑
  • 依赖于线程执行的顺序 - 即使我们首先启动一个线程,也不能保证它将首先被执行。

关于多线程要记住什么

  • 调用start()方法启动一个 Thread。
  • 可以Thread直接扩展类以使用线程。
  • 可以在Runnable接口内实现线程动作。
  • 线程优先级取决于JVM实现。
    自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

针对以上面试题,小编已经把面试题+答案整理好了

最新大厂必问微服务面试题汇总:SpringCloud、Boot、Dubbo

最新大厂必问微服务面试题汇总:SpringCloud、Boot、Dubbo

最新大厂必问微服务面试题汇总:SpringCloud、Boot、Dubbo

面试专题

image

除了以上面试题+答案,小编同时还整理了微服务相关的实战文档也可以分享给大家学习

image

image

image
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
…(img-VRiUZEXZ-1712611886593)]

[外链图片转存中…(img-qta7kkxR-1712611886593)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_74530944/article/details/137532812

智能推荐

【Unity】Unity Editor中使输入框失去焦点_guiutility.keyboardcontrol-程序员宅基地

文章浏览阅读2.2k次。【Unity】Unity Editor中使输入框失去焦点Unity自定义编辑器窗口时,如果想让当前正在输入文本的输入框失去焦点,必须把焦点移动到另一个输入控件。如果用代码使当前输入框失去焦点的话,很简单,就一行代码:GUIUtility.keyboardControl = 0;..._guiutility.keyboardcontrol

Linux阅码场 - Linux内核月报(2020年06月)-程序员宅基地

文章浏览阅读1.4k次。关于Linux内核月报Linux阅码场Linux阅码场内核月报栏目,是汇总当月Linux内核社区最重要的一线开发动态,方便读者们更容易跟踪Linux内核的最前沿发展动向。限于篇幅,只会对..._memory tag

c++ pair make_pair_make_pair返回值-程序员宅基地

文章浏览阅读193次。pair 的用法std::pair主要的作用是将两个数据组合成一个数据,两个数据可以是同一类型或者不同类型。C++标准程序库中凡是“必须返回两个值”的函数, 也都会利用pair对象。class pair可以将两个值视为一个单元。容器类别map和multimap就是使用pairs来管理其健值/实值(key/value)的成对元素。pair被定义为struct,因此可直接存取pair中的个别值..._make_pair返回值

微信公众号开发工具汇总-程序员宅基地

文章浏览阅读8.4k次。前面写了篇入坑指南,介绍了下开发微信公众号的基本流程。最近又捣鼓了一阵,发现这开发工具的选择对于提高开发效率真是有莫大的帮助,所谓“只要工具选得好,月底奖金跑不了”。今天得空,笔者就给各位老哥列举几个绝对能派上用场的小工具,保证没毛病!微信公众平台技术文档这货实际上是必需品,没了它,您还真是寸步难行。官方文档包含了一个产品最直接也最全面的说明,在微信公众平台技术文档中,详细说明了微信公众号开发的概念_微信公众号开发工具

获得硬盘ID(序列号、机器码)的C++代码源码_硬盘id获取 c++-程序员宅基地

文章浏览阅读612次。获得硬盘的序列号(ID/机器码)的C++源码_硬盘id获取 c++

VRRP协议介绍_vrrp是什么协议-程序员宅基地

文章浏览阅读1w次,点赞5次,收藏60次。1.VRRP的工作原理2.Master路由器和Backup路由器3.VRRP报文格式4.虚拟路由器中的虚拟IP地址和虚拟MAC 地址_vrrp是什么协议

随便推点

使用指针实现字符串拷贝_字符指针拷贝-程序员宅基地

文章浏览阅读488次。【代码】使用指针实现字符串拷贝。_字符指针拷贝

Qt自定义控件9:波浪进度条1_qt 波浪进度球-程序员宅基地

文章浏览阅读502次。Qt自定义控件8:波浪进度条1先看效果图:思路:利用QPaintPath画出封闭路径,填充颜色,圆弧使用正弦函数,根据横坐标递增,画出正弦函数线。关键代码:void WaterProgressBar1::paintEvent(QPaintEvent *event){ int width = this->width(); int height = this->h..._qt 波浪进度球

5G协议批量下载 python3_批量下载3gpp 协议-程序员宅基地

文章浏览阅读673次。最近需要3GPP的5G协议,手动一个一个下载比较麻烦,抽空用python3写了个下载程序,可以从3gpp的ftp服务器批量下载协议文件。3GPP协议下载地址:https://www.3gpp.org/ftp/Specs/archive/38_series/代码使用了线程池,可以多线程从3gpp下载协议。代码流程:1、首先从下载地址获取要下载的所有文件的 文件名、url、大小、日期、本地存储地址,写入ini文件2、读取ini文件中的信息,使用线程池进行文件下载#coding:utf-_批量下载3gpp 协议

删除字符串中的所有相邻重复项python(leetcode1047)_python删除相邻字符,可得不同字符串-程序员宅基地

文章浏览阅读869次,点赞3次,收藏2次。删除字符串中的所有相邻重复项_python删除相邻字符,可得不同字符串

Python与各个编程语言对比_python 对比其他语言-程序员宅基地

文章浏览阅读134次。高级语言将与计算机架构的交互抽象化,你可以输入代码字(code word,比如 for 循环或变量定义),高级语言会将其编译成计算机可以执行的代码,而低级语言会直接处理这些代码字。有许多用 Python 编写的框架与 Node.js 类似,像 Flask 和 Django,但 Node.js 是用 JavaScript 语言编写的。正因为这一点,我们选择用 Python。同时学习 R(或 MATLAB)和 Python,你可以根据具体项目需求来选择使用哪种语言,这样可以更好地满足项目的需求,也更加方便。_python 对比其他语言

QGIS基本功 | 21 QGIS工程文件属性设置(2)——坐标参照系、变换、默认样式、数据源、关系和变量_qgis如何以原始坐标系-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏12次。今天继续分享工程文件属性的设置,包括工程坐标参照系、变换、默认样式、数据源、关系和变量六个部分。01坐标参照系工程坐标参照系定义了当前地图窗口所使用的坐标系,决定了如何将数据从其底层原始坐标绘制到QGIS地图画布中,并呈现为平面地图。QGIS支持自动动态投影,不管图层自带的坐标系是否与工程坐标系相同,均可自动重投影到当前工程坐标系,使数据可以正确叠加显示,这个过程对用户是完全透明的。因此,工程坐标系是各个图层正确显示的基础,为了使地图减少形变、正确反应现实世界地物的大小和相..._qgis如何以原始坐标系

推荐文章

热门文章

相关标签