Java多线程:线程的优先级 || 线程的中断 || 线程的分类 || 线程的定时器

news2025/1/18 9:53:27

Java多线程:线程的优先级 || 线程的中断 || 线程的分类 || 线程的定时器

在这里插入图片描述


每博一文案

正如村上春树所说:“当暴风雨过去,你不会记得自己是如何度过的,你甚至不确定,暴风雨是否真正结束了,
但你已不再是当初走进暴风雨的那个人了。这就是暴风雨的意义。”
一个人经历过挫折,才会更好的成长,经历这些才能珍惜所拥有的。
佛说:“无论你遇到谁,他都是对的人,无论发生什么事,那都是唯一会发生的事。”
有些人的出现,从一开始就不是为了大结局,而是为了给生活增加一段插曲。
只是为了经由那个人,让你更了解自己,所以遇到谁,有过怎样的故事,都是人生的宝贵财富。
比起抽刀断水的决绝,人更怕的是自我感动,明明付错心等错人,却还说着可以为爱一无所有。
明知道走错了路,回头就行,明知道爱错了人,放手就好。
但对于付出过真心的东西,总有不舍得立刻叫停,总觉得再坚持一下也许就会找到出路。
结局却往往是拖泥又带水,蹉跎一日复一日。
有这样一段话:“成长是一个人的朝圣路,没有一个人能够助另一个人成长,再多的左突右突和痛苦,我们都要像蝉一样,蜕一层皮,
然后把内心的痛苦和恐惧不安统统丢掉。”
人之相遇,已是不易,若能相知相伴,更是少之又少。并不是每一段爱都会开花结果。但可以肯定的是,每一份爱都曾化为
成长的力量,在无数的黑暗的夜里默默温暖着我们。
茫茫人海中的相遇,已然胜过所有的悲欢。或是痛苦,或是美好,都是一种经历,经历过就是收获,又何必在乎结局如何。
因此,不要害怕去爱,不要害怕被爱,希望你明白,爱错了人也不怕,因为凡是经历,皆为成长。
                                 ——————   一禅心灵庙语

文章目录

  • Java多线程:线程的优先级 || 线程的中断 || 线程的分类 || 线程的定时器
    • 每博一文案
    • 一. 线程的优先级
    • 二. 线程的中断
    • 三. 线程的分类
    • 四. 线程的定时器
    • 五. 总结:
    • 六. 最后:


一. 线程的优先级

对于线程的优先级的使用 Thread 类中的 getPriority() 获取当前线程的优先级和 setPriority(int newPriority) 设置线程的优先级

在这里插入图片描述

在这里插入图片描述

需要注意的是:线程的优先级是在 [10~1] 之间的,其中 5 是默认线程的优先级

  • MIN_PRIORITY = 1 线程的最小优先级
  • NORM_PRIORITY = 5 线程的默认优先级
  • MAX_PRIORITY = 10 线程的最大优先级
  • 当所设置的线程优先级,不再 [10~1] 这个区间内报:IllegalArgumentException 非法参数异常。

在这里插入图片描述
在这里插入图片描述

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

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

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

补充:

  • 线程创建时继承父线程的优先级
  • 低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被调用,高优先级的线程也不是一定就比低的优先级线程先执行,只是先被执行的概率更高而已,注意是 概率不是绝对

如下

package blogs.blog4;

public class ThreadTest11 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyThread11());  // 线程一
        Thread t2 = new Thread(new MyThread11());  // 线程二
        Thread t3 = new Thread(new MyThread11());  // 线程二
        Thread t4 = new Thread(new MyThread11());  // 线程二

        // 设置线程名
        t1.setName("线程一");
        t2.setName("线程二");
        t3.setName("线程三");
        t4.setName("线程三");

        // 设置线程的优先级
        t1.setPriority(Thread.MIN_PRIORITY);  // 最小 1
        t2.setPriority(Thread.NORM_PRIORITY); // 默认 5
        t3.setPriority(Thread.MAX_PRIORITY);  // 最大 10
        t4.setPriority(6);   // 设置为 6

        // 创建新线程
        t1.start();
        t2.start();
        t3.start();
        t4.start();

    }
}


class MyThread11 implements Runnable {
    @Override
    public void run() {        // Thread.currentThread().getPriority() 获取当前线程的优先级
        System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
    }
}

在这里插入图片描述


二. 线程的中断

关于线程 interrupt() 大家可以移步至 🔜🔜🔜 https://blog.csdn.net/mr_zhuqiang/article/details/45917551

关于线程 isInterrupted() 大家可以移步至 🔜🔜🔜 https://leixiaoheng.blog.csdn.net/article/details/126423041

三. 线程的分类

  • Java中的线程分为两类:一种是守护线程 ,另一种是 用户线程

  • 它们在几乎每个方法都是相同的,唯一的区别是判断 JVM 何时离开。

  • 默认创建的线程没有特殊处理的话,就是一个用户线程 , main 主线程就是一个用户线程

  • 守护线程: 是用来服务用户线程的,通过在 start() 方法前调用, thread.setDaemon(true) 可以将一个用户线程变成一个守护线程。注意是:在 start() 方法创建新线程之前,调用 thread.setDaemon(true) 对象方法,不然会报:IllegalThreadStateException 非法线程状态异常

  • Java 垃圾回收就是一个典型的守护线程

  • 守护线程的特点: 当所有用户线程都结束了,守护线程会自动结束。用户线程不会

  • 守护线程用在什么地方呢 ???

    • 每天 0:00 的时候,系统数据自动备份。这个需要使用到定时器,并且我们可以将定时器设置为守护线程,一直在哪里看着,每到 0.00的时候就备份一次。所有的用户线程如果结束了,守护线程自动退出,没有必要进行数据备份了。
      在这里插入图片描述

举例:创建一个用户线程:main 主用户线程,和一个 守护线程 : t1 ,在main 主用户线程中定义一个当 for(int i )循环 中的 i == 5时,抛出 int num = 1/0; 的算数异常终止 main 主用户线程的执行。同样的 t1 守护线程也会停止

package blogs.blog4;

/**
 * 守护线程的设置
 */
public class ThreadTest12 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyThread12());

        t1.setName("t1 用户线程");
        // 将用户线程修改为 守护线程
        t1.setDaemon(true);

        Thread.currentThread().setName("main 主线程");

        // 创建新线程
        t1.start();

        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);
            if (i == 5) {
                int num = 1 / 0;  // 让main 主用户线程异常终止
            }
        }
    }
}


class MyThread12 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);

            try {
                Thread.sleep(6);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述


在这里插入图片描述


如果两个是用户线程,各自执行各自的线程的(弹栈压栈),互不影响,就是 main 主用户线程终止,其他用户线程也不会终止。

package blogs.blog4;

/**
 * 守护线程的设置
 */
public class ThreadTest12 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyThread12());

        t1.setName("t1 用户线程");

        Thread.currentThread().setName("main 主线程");

        // 创建新线程
        t1.start();

        // main 主用户线程
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);
            if (i == 5) {
                int num = 1 / 0;  // 让main 主用户线程异常终止
            }
        }
    }
}


class MyThread12 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);

            try {
                Thread.sleep(6);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述


四. 线程的定时器

定时器的使用指定定时任务:

定时器的作用: 间隔特定的时间,执行特定的程序,每周要进行银行账户的总账操作。

在实际的开发中,每隔多久执行一段特定的程序,这种需求是很常见的,

那么在Java中其实可以采用多种方式实现:

可以使用sleep 方法,睡眠,设置睡眠时间,没到这个时间点醒来,执行任务,这种方式是最中原始的定时器 (比较Low)

在Java的类库种已经写好了一个定时器,ava.util.Timer可以直接拿来用。不过,这种方式在目前的开发中也很少用,因为现在有很多高级框架都是支持定时任务的。

在实际开发中,目前使用较多的是Spring框架中提供的SpringTask框架,这个框架只要进行简单的配置,就可以完成定时器的任务。

步骤:

  1. 创建一个 extends abstract TimerTask 抽象类的子类,并重写其中 TimerTaskimplement Runnable 的 run () 方法。
class LogTimerTask extends TimerTask {
    // 2. 重写 Runnable 中的 run()方法
    @Override
    public void run() {
        // 编写你需要执行的任务就行了
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String strTime = simpleDateFormat.format(new Date());  // 现在的时间点
        System.out.println(strTime + ": 成功完成了一次数据备份");
    }
}

因为 TimerTask是 implement Runnable 接口的

public abstract class TimerTask implements Runnable {
}

在这里插入图片描述


  1. 创建定时器Timer 的 实例对象
Timer timer = new Timer();

也可以创建守护线程(当用户线程结束了,守护线程自动结束)的方式创建定时器对象 Thread 对象

Timer timer2 = new Timer(true);

在这里插入图片描述

Timer 对于的构造器

在这里插入图片描述

  1. 指定:定时任务 调用 timer.schedule()对象方法
public void schedule(TimerTask task, Date firstTime, long period);
// timer.schedule(定时任务,第一次执行时间,间隔多久执行一次(单位:毫秒));
/*
1000 *60 一分钟
1000 * 60 * 60 一个小时
1000 * 60 * 60 *24 一天
1000 * 60 * 60 * 24 * 365 一年
*/

在这里插入图片描述

完整实现步骤如下:

package blogs.blog4;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 定时器
 */
public class ThreadTest13 {
    public static void main(String[] args) {
        // 3.创建定时器对象
        Timer timer = new Timer();
        // 这里我们也可以创建守护线程(当用户线程结束了,守护线程自动结束)的方式创建定时器对象
        Timer timer2 = new Timer(true);

        // 4.指定:定时任务 调用 timer.schedule()对象方法
        // timer.schedule(定时任务,第一次执行时间,间隔多久执行一次(单位:毫秒));

        // 设置时间类型
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date firstTime = null;

        try {
            firstTime = sdf.parse("2023-01-11 21:25:10");
        } catch (ParseException e) {
            e.printStackTrace();
        }

        timer.schedule(new LogTimerTask(), firstTime, 1000 * 10);  // 间隔十秒

    }
}


// 编写一个定时任务类
// 假设是一个记录日志的定时任务
// public abstract class TimerTask implements Runnable
// 1.创建一个 extends TimerTest 类的子类
class LogTimerTask extends TimerTask {
    // 2. 重写 Runnable 中的 run()方法
    @Override
    public void run() {
        // 编写你需要执行的任务就行了
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String strTime = simpleDateFormat.format(new Date());  // 现在的时间点
        System.out.println(strTime + ": 成功完成了一次数据备份");
    }
}

在这里插入图片描述


五. 总结:

  1. 对于线程的优先级的使用 Thread 类中的 getPriority() 获取当前线程的优先级和 setPriority(int newPriority) 设置线程的优先级。
  2. 线程的优先级是在 [10~1] 之间的,其中 5 是默认线程的优先级。当所设置的线程优先级,不再 [10~1] 这个区间内报:IllegalArgumentException 非法参数异常。
  3. 低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被调用,高优先级的线程也不是一定就比低的优先级线程先执行,只是先被执行的概率更高而已,注意是 概率不是绝对
  4. 守护线程: 是用来服务用户线程的,通过在 start() 方法前调用, thread.setDaemon(true) 可以将一个用户线程变成一个守护线程。注意是:在 start() 方法创建新线程之前,调用 thread.setDaemon(true) 对象方法,不然会报:IllegalThreadStateException 非法线程状态异常
  5. 默认创建的新线程是用户线程 main 是用户线程,Java 中的 垃圾回收线程是守护线程。
  6. 守护线程的特点: 当所有用户线程都结束了,守护线程会自动结束。用户线程不会
  7. 定时器的作用: 间隔特定的时间,执行特定的程序,每周要进行银行账户的总账操作。

六. 最后:

限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见 !!!

在这里插入图片描述

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

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

相关文章

分布式唯一ID的几种生成方案,一次性全掌握!

上一篇文章&#xff0c;我们聊了一下分库分表相关的一些基础知识&#xff0c;具体可以参见&#xff1a;《用真实业务场景告诉你&#xff0c;高并发下如何设计数据库架构&#xff1f;》。 这篇文章&#xff0c;我们就接着分库分表的知识&#xff0c;来具体聊一下全局唯一id如何…

Flutter 基础-上

一、初始化项目 Material Design (Google 推出的前端UI 解决方案) 官网: https://www.material.io/中文网: https://material-io.cn/ Flutter 中一切内容都是组件(Widget) 无状态组件(StatelessWidget)有状态组件(StatefulWidget) 二、app结构 MaterialApp title (任务管理器…

【VScode技巧】:platformio部署ESP32Cam开发板

学习目标&#xff1a; 前几天用Arduino开发了ESP32Cam&#xff0c;实现了人脸识别的功能&#xff0c;今天无聊想了想ESP32Can也可以在VScode的Platformio中使用&#xff0c;于是就试着配置了一下。以下是配置环境的过程&#xff0c;谢谢大家观看。 正所谓工欲善其事&#xff0c…

【零基础】学python数据结构与算法笔记10

文章目录前言57.链表介绍58.链表的创建和遍历59.链表的插入和删除60.双链表61.链表总结62.哈希表62.哈希表实现64.哈希表应用总结前言 学习python数据结构与算法&#xff0c;学习常用的算法&#xff0c; b站学习链接 57.链表介绍 链表是由一系列节点组成的元素集合。每个节点…

React配置文件(五) 配置less

代码如下: module.exports { webpack: override( addLessLoader({ lessOptions: { javascriptEnabled: true, modifyVars: { primary-color: #1DA57A }, }, }), adjustStyleLoaders(({ use: [, , postcss] }) > { const postcssOptions postcss.options postcss.options …

SEO初学者如何快速做好 SEO 优化?seo数据查询

昨天给大家介绍了seo的意义和重要性&#xff0c;今天让我们一起看看10个基本的SEO初学者技巧&#xff0c;如何优化网站以增加流量。 1. 研究关键词并使用尾词 关键词在SEO中起着重要的作用。关键字表明了你文章的主要主题&#xff0c;它使人们有可能在网上搜索感兴趣的主题时找…

RK3588平台开发系列讲解(日志篇)RK3588 syslog的使用

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、查看是否启用syslog.conf二、配置启用syslog.conf1、配置busybox2、添加配置文件3、编译buildroot烧录三、验证1、编写测试代码2、查看日志文件3、运行测试程序沉淀、分享、成长,让自己和他人都能有所收获!😄 …

SpringCloudAlibaba入门(2023版)

先知 架构图一览 创建Serve端 新建项目 配置文件 application.yaml server:port: 8080# Eureka配置 eureka:instance:## Eureka实例的名称hostname: localhostAclient:# false表示自己端就是注册中心&#xff0c;职责就是维护服务实例&#xff0c;并不需要去检查服务fetch-r…

Kafka-eagle 安装教程

参考资料&#xff1a; 参考视频 Kafka-eagle官网 解释&#xff1a;Kafka-eagle 后来更名为 EFAK &#xff0c;所以打开官网会显示EFAK 环境准备&#xff1a; 要有本服务器可访问的MySQL服务&#xff0c;远程的请检查是否已经开启了MySQL远程访问&#xff0c;如果没有则需…

1.12 PWM实验

蜂鸣器--------TIM4 CH1/PB6 风扇-----------TIM1 CH1/PE9 马达-----------TIM16 CH1/PF6 一.PWM框图 RCC&#xff1a;使能GPIOB GPIOB&#xff1a;设置复用功能 TIM4:产生方波 二.分析RCC 确定总线&#xff0c;使能GPIOB和TIM4&#xff0c;GPIOE和TIM1,GPIO和TIM16 三.分…

【C++11】右值引用和移动语义

目录 一、左值 vs 右值 二、左值引用vs 右值引用 三、右值引用使用场景和意义 1. 左值引用的使用场景 2. 左值引用的短板 3. 右值引用和移动语义解决上述问题 四、右值引用引用左值的使用场景 五、完美转发 1. 模板中的&& 万能引用 2. std::forward 完美转发…

windows排查问题常用命令

查看JAVA进程占用PID: wmic process where caption"java.exe" get processid,caption,commandline /value查看进程端口信息&#xff1a;netstat -ano 或者 netstat -ano|findstr "8080" 或查看成功建立连接的&#xff1a;netstat -ano | findstr “ESTABLI…

C语言中的字符指针

目录1.字符指针指向一个字符2.字符指针指向一个字符串3.例题1.字符指针指向一个字符 int main() {char ch w;char *pc &ch;return 0; }将一个char类型的变量的地址放到一个char*类型的指针里去&#xff0c;这里的char*ps就是字符指针 在这里的字符指针与之前的整形指针等…

巧用gitbash的scp命令实现跨网段的文件直传

背景 嵌入式开发的工作流一般是这样的&#xff0c;程序员通过Windows电脑登陆Linux服务器&#xff0c;在服务器上编译出二进制文件后&#xff0c;先将文件scp到本地&#xff0c;然后再scp到Linux开发板&#xff0c;如下图所示 这样做需要执行两次scp命令&#xff0c;能否只执…

Golang cgo:如何在Go代码中调用C语言代码?

如何在Go代码中调用C语言代码&#xff1f; Go语言是通过自带的一个叫CGO的工具来支持C语言函数调用&#xff0c;同时我们可以用Go语言导出C动态库接口给其它语言使用。 方式一、直接在 Go 代码中写入 C 代码 检查是否开启cgo工具 首先&#xff0c;要查看是否已经开启cgo工具…

树状数组+例题

一、树状数组的定义 树状数组 或 二元索引树&#xff08;Binary Indexed Tree&#xff09;&#xff0c;现多用于高效计算数列的前缀和&#xff0c; 区间和。它可以以 log(n)log(n)log(n) 的时间得到任意前缀和&#xff0c;也支持在log(n)log(n)log(n)时间内支持动态单点值的修改…

Spring简介与使用

什么是spring spring是一个开源的框架&#xff0c;里面有一系列功能&#xff0c;可以使我们的开发变得更为轻松 简单来说&#xff0c;spring是包含众多工具方法的IoC容器 所谓容器&#xff0c;就是盛放东西的事务&#xff0c;例如我们的ArrayList就是数据存储的容器&#xff…

数据库——排序与分页

目录 排序数据 单列排序 多列排列 分页 分页原理 优点 MySQL 8.0新特性 排序数据 使用 ORDER BY 子句排序ASC&#xff08;ascend&#xff09;: 升序DESC&#xff08;descend&#xff09;:降序ORDER BY 子句在SELECT语句的结尾。 单列排序 SELECT employee_id,last_name…

【Linux】项目自动化构建工具-make与Makefile的简单使用(模拟实现进度条)

目  录1 make与Makefile使用2 模拟实现进度条前言&#xff1a; 会不会编写Makefile&#xff0c;从侧面说明了一个人是否具备完成大型工程的能力。一个工程中的源文件不计其数&#xff0c;按类型、功能、模块分别放在若干个目录中&#xff0c;Makefile定义了一系列的规则来指定…

使用 EMQX Cloud 桥接数据到 GCP Pub/Sub

前不久&#xff0c;Google 宣布其旗下的 GCP IoT Core 即将在 2023 年 8 月 16 日停止提供服务。这意味着大量使用 GCP IoT Core 的用户可能需要将他们的 IoT 应用迁移到其他物联网云服务。除了云服务的迁移&#xff0c;很多用户也在直接利用谷歌云生态&#xff0c;使用 GCP 上…