Java线程学习笔记

    1、判断线程存活

   

        1. 当线程run()或者call()方法执行结束,线程进入终止状态

        2. 当线程内发生异常,并且异常没有被捕获,线程进入终止状态

        3. 线程调用stop()方法后,线程进入终止状态(不推荐使用)

       

        当主线程结束时,其他线程不受任何影响,并不会随之结束。一旦子线程启动起来后,它就拥有和主线程相同的地位,它不会受主线程的影响。

        为了测试某个线程是否已经死亡,可以调用线程对象的isAlive()方法,当线程处于就绪、运行、阻塞3种状态时,该方法将返回true;当线程处于新建、死亡2种状态时,该方法将返回false。

/**

 * isAlive()方法练习

   */

   public class IsAliveDemo1 {

   public static void main(String[] args) throws InterruptedException {

       Thread t = new Thread(()->{

           for (int i = 0; i < 50; i++) {

               System.out.println(i);

           }

       });

       System.out.println("线程的状态:"+t.getState());//NEW

       System.out.println("线程启动前:"+t.isAlive());//false

       System.out.println("----------------------");

       t.start();

       System.out.println("线程的状态:"+t.getState());//RUNNABLE

       System.out.println("线程启动后:"+t.isAlive());//true

       System.out.println("----------------------");

       TimeUnit.SECONDS.sleep(5);

       System.out.println("线程的状态:"+t.getState());//TERMINATED

       System.out.println("线程结束后:"+t.isAlive());//false

   }

   }

/**

 *isAlive()方法练习2

 */

public class IsAliveDemo2 {

    public static void main(String[] args) throws InterruptedException {

        Thread t = new Thread(()->{

            for (int i = 0; i < 40; i++) {

                System.out.println(i);

                if(i==15){

                    synchronized (IsAliveDemo2.class){

                        try {

                            IsAliveDemo2.class.wait();

                        } catch (InterruptedException e) {

                            throw new RuntimeException(e);

                        }

                    }

                }

            }

        });

        //启动前获取状态

        System.out.println("线程启动前:"+t.isAlive());

        t.start();

        System.out.println("线程启动后:"+t.isAlive());

        //主线程休眠2秒,给予t线程充足的执行时间

        TimeUnit.SECONDS.sleep(2);

        System.out.println("线程抛出异常后:"+t.isAlive());

    }

}

       

        注意:不要对处于死亡状态的线程调用start()方法,程序只能对新建状态的线程调用start()方法,对新建状态的线程两次调用start()方法也是错误的。这都会引发IllegalThreadState Exception异常。

/**

 * 练习3

   */

   public class IsAliveDemo3 {

   public static void main(String[] args) throws InterruptedException {

       Thread t = new Thread(()->{

           for (int i = 0; i < 10; i++) {

               System.out.println(i);

           }

       });

       t.start();

       //t.start(); 抛出IllegalThreadStateException异常

       TimeUnit.SECONDS.sleep(2);

       System.out.println(t.getState());//TERMINATED

       //t.start(); 抛出IllegalThreadStateException异常

   }

   }

   2、线程控制

   (1)Join()

    join()方法相当于插入,例如在T2线程中调用了线程T1.join()方法,则T2线程会一直等待T1线程执行结束后再继续执行。

    就是在A线程中调用线程B的join()方法,线程A会一直等待直到线程B执行结束再执行,也可以理解为插队。

   

    注意:当T2线程执行过程中被T1线程Join,线程T1执行时,T2处于WAITING

/**

 * Join()方法

   */

   public class JoinDemo1 {

   public static void main(String[] args) throws InterruptedException {

       Thread t1 = new Thread(()->{

           for (int i = 0; i < 30; i++) {

               System.out.println(Thread.currentThread().getName()+"--------->"+i);

           }

       },"t1");

       Thread t2 = new Thread(()->{

           for (int i = 0; i < 30; i++) {

               System.out.println(Thread.currentThread().getName()+"#########"+i);

               if (i == 10){

                   try {

                       //t1线程调用t2线程的join()方法,插队执行

                       t1.join();

                   } catch (InterruptedException e) {

                       throw new RuntimeException(e);

                   }

               }

           }

       },"t2");

       t1.start();

       System.out.println(t1.getState());

       t2.start();

       //main t1 t2 三个线程交替执行

       for (int i = 0; i < 60; i++) {

           System.out.println(Thread.currentThread().getName()+"***********"+i);

       }

   }

   }


 

   (2)Join(long millis)

    如果T2线程执行过程中调用为了T1线程的join(long millis)方法,T2线程最多等待T1线程millis毫秒,到达时间后,如果T1线程没有结束,则和T2线程交替执行。

   

    注意:T2线程被T1线程join(millis)后,T2线程在等待T1线程执行的过程中处于TIMED_WAITING状态    

/**

 * Join()方法

   */

   public class JoinDemo2 {

   public static void main(String[] args) throws InterruptedException {

       Thread t1 = new Thread(()->{

           for (int i = 0; i < 50; i++) {

               System.out.println(Thread.currentThread().getName()+"-------->"+i);

               try {

                   TimeUnit.SECONDS.sleep(1);

               } catch (InterruptedException e) {

                   throw new RuntimeException(e);

               }

           }

       },"t1");

       Thread t2 = new Thread(()->{

           for (int i = 0; i < 200; i++) {

               System.out.println(Thread.currentThread().getName()+"##########"+i);

               if (i == 20){

                   //启动t1线程

                   t1.start();

                   try {

                       //在线程t2中插入

                       t1.join(3000);

                   } catch (InterruptedException e) {

                       throw new RuntimeException(e);

                   }

               }

           }

       },"t2");

       //启动进程

       t2.start();

       System.out.println("--------------------");

       //主线程休眠 让t2线程执行

       TimeUnit.SECONDS.sleep(2);

       //t2线程的状态

       System.out.println(t2.getState());//TIMED_WAITING

   }

   }

   (3)守护线程

    在后台运行的,并为其他的线程提供服务的线程被称为“后台线程”,又称为“守护线程”,JVM的垃圾回收线程就是典型的后台线程。

    特征:如果所有的前台线程都死亡,后台线程会自动死亡。

   

    守护线程必须在启动前将其守护状态设置为true,启动之后不能再将用户线程设置为守护线程,否则JVM会抛出一个InterruptedException异常。具体来说,如果线程为守护线程,就必须在线程实例的start()方法调用之前调用线程实例的setDaemon(true),设置其daemon实例属性值为true。

    守护线程存在被JVM强行终止的风险,所以在守护线程中尽量不去访问系统资源,如数据库连接。守护线程被强行终止时,可能会引发系统资源操作不负责任的中断,从而导致资源不可逆的损坏。

    守护线程创建的线程也是守护线程。在守护线程中创建的线程,新的线程都是守护线程。在创建之后,如果通过调用setDaemon(false)将新的线程显式地设置为用户线程,新的线程可以调整成用户线程。

/**

 * setDaemon()方法

   */

   public class DaemonDemo {

   public static void main(String[] args) {

       Thread t1 = new Thread(()->{

           for (int i = 0; i < 100; i++) {

               System.out.println(Thread.currentThread().getName()+"===="+i);

           }

       },"t1");

       //设置线程为守护线程 必须在启动前设置

       t1.setDaemon(true);

       t1.start();

       //主线程循环次数大幅少于守护线程,当前台线程执行结束时 守护线程不管是否执行完毕都会结束

       for (int i = 0; i < 10; i++) {

           System.out.println(Thread.currentThread().getName()+">>>>"+i);

       }

   }

   }


 

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

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

相关文章

下一代人工智能的设计思路

大模型扭转了此前人工智能研究的思路&#xff0c;放弃了可解释性&#xff0c;而开始拥抱复杂网络和大规模参数。 这些让现代神经网络的能力超越前代&#xff0c;但也带来了不少问题。 巨大的成本&#xff1a;训练模型需要的数据和算力都是海量&#xff0c;动辄数百万千万&…

Redis 内存淘汰策略有哪些?过期数据如何删除?

Redis 在面试中出现的概率非常大&#xff0c;毕竟后端项目如果用到分布式缓存的话&#xff0c;一般用的都是 Redis。目前&#xff0c;还没有出现一个能够取代 Redis 的分布式缓存解决方案。 这篇文章中&#xff0c;我会分享几道 Redis 内存管理相关的问题&#xff0c;都很常见…

Redis的过期策略

Redis 支持的过期策略主要有以下几种&#xff1a; 定时过期(Timed Expiration) 这种策略会在设置键的过期时间时&#xff0c;创建一个定时器&#xff0c;当达到指定的过期时间点时&#xff0c;立即执行删除操作。这种方式可以精确控制键的生命周期&#xff0c;但是如果有大量的…

uniapp引入第三方字体库如(宋体、喜鹊燕书体、字小魂歌以晓手迹行楷体等) 最优解决方案

最近在开发一个写对联的小程序&#xff0c;其中要求对联文字以不同字体呈现&#xff0c;比如&#xff08;宋体、喜鹊燕书体、字小魂歌以晓手迹行楷体等&#xff09;&#xff0c;如图&#xff1a; 一般UI设计给的都是这种.tff格式的字体文件&#xff0c;如图&#xff1a; 那么…

猫咪主食冻干真的对猫好吗?最热门的三款主食冻干对比测评

随着对猫咪主食健康和营养问题的关注度提高&#xff0c;越来越多的铲屎官开始重视科学养猫。 主食冻干因其模拟猫咪原始捕猎猎物模型配比、低温加工的特点&#xff0c;被认为是最符合猫咪饮食天性的选择。 相比传统的膨化猫粮&#xff0c;主食冻干中的淀粉和碳水化合物添加较…

如何删除mysql-bin

“删除mysql-bin”,用于记录一下后面还会用到. 删除mysql-bin的方法&#xff1a; 1、通过“mysql> reset master;reset slave;”命令删除“mysql-bin”文件&#xff1b;2、删除“my.cnf”中的“log-binmysql-bin”一行即可。 默认情况下mysql会一直保留mysql-bin文件&…

QT基础篇(2)QT5模板库,工具类及控件

1.字符串类 QT中的字符串类包括以下几种&#xff1a; QString类&#xff1a;是Qt中最常用的字符串类&#xff0c;用来存储Unicode字符。它支持各种字符串操作&#xff0c;例如连接、替换、截取等。 QByteArray类&#xff1a;用来存储字节序列&#xff0c;适用于处理非Unicode…

计算机网络 物理层

文章目录 物理层物理层的基本概念数据通信的基础知识数据通信系统的模型有关信道的几个基本概念信道的极限容量 物理层下面的传输媒体导引型传输媒体非引导型传输媒体 信道复用技术波分复用码的复用 宽带接入技术ADSL 技术光纤同轴混合网 (HFC 网&#xff09;FTTx 技术 物理层 …

爬虫01-爬虫原理以及爬虫前期准备工作

文章目录 1 爬虫基本原理什么是爬虫爬虫功能详解爬虫基本流程两个概念&#xff1a;request和response 2 一些问题爬虫能抓取什么样的数据&#xff1f;抓取的数据怎么提取部分内容&#xff1f;数据解析方式。为什么我爬虫抓取的数据和浏览器看到的不一样怎样解决JavaScript渲染的…

阿里云弹性计算技术公开课-ECS 安全季 全新上线!

云布道师 如何保障云上业务的应用安全和数据安全&#xff0c;是每一个上云的企业和用户关注的重点。云上安全建设是一个体系化工程&#xff0c;需要用户主动进行多方面的考虑和实施&#xff0c;包括制定完善的安全策略和规范&#xff0c;如身份认证、访问控制、漏洞管理、安全…

超实用的公众号内容制作流程,小白也能轻松学会

公众号是以内容为王的平台&#xff0c;保持优质原创内容发布可以给公众号带来源源不断的流量&#xff0c;稳定输出内容&#xff0c;会获得平台的流量扶持。 很多小伙伴运营公众号都没有什么阅读量&#xff0c;一方面是公众号内容同质化越来越严重&#xff0c;另外一方面是公众…

编程笔记 html5cssjs 030 HTML音频

编程笔记 html5&css&js 030 HTML音频 一、<audio>元素二、属性三、事件三、使用 CSS 设置样式练习小结 有时候网页上也需要嵌入音频。比如播放歌曲或老师讲课的音频等。 一、<audio>元素 <audio> HTML 元素用于在文档中嵌入音频内容。<audio>…

寒假刷题第四天

PTA甲级 1017 Queueing at Bank 可以使用小顶堆模拟窗口的情况&#xff0c;一定是最小的时间的窗口先空出来 #include<iostream> #include<algorithm> #include<queue> #include<vector>using namespace std;struct people {int time;int process; …

完全卸载grafana

查看要卸载的包的名字 yum list installed yum remove grafana-enterprise.x86_64 成功

【tensorflowflutterweb】机器学习模型怎样用到前端上(未写完)

书接上回 在上一章 我们谈了怎么根据项目需求构建一个简单的机器学习模型。 ​​​​​​ ​​​​​​【tensorflow&flutter】自己写个机器学习模型用在项目上&#xff1f;-CSDN博客文章浏览阅读852次&#xff0c;点赞22次&#xff0c;收藏15次。【tensorflow&flutter…

【2023 - 探索】博0到博1,游戏新地图的探索日志

【2023 - 探索】博0到博1&#xff0c;游戏新地图的探索日志 写在最前面CSDN探索日志2023的探险 探索日志年终回顾探索 冒险回顾实习6月开始跟着老师做科研年中的一些其他事情9月开始上课开学后11月&#xff0c;读者互动 新年展望新年祝福 写在最前面 2023&#xff0c;我解锁了新…

C语言——结构体类型(二)【结构体内存对齐,结构体数组】

&#x1f4dd;前言&#xff1a; 上一讲结构体类型&#xff08;一&#xff09;中&#xff0c;我们讲述了有关结构体定义&#xff0c;创建&#xff0c;初始化和引用的内容&#xff0c;这一讲&#xff0c;我们进一步学习结构体的相关知识&#xff1a; 1&#xff0c;结构体内存对齐…

腾讯云2024年优惠券领取入口汇总

腾讯云是国内知名的云计算服务提供商&#xff0c;提供了包括云服务器、云数据库、云存储、人工智能等全方位的云服务。为了吸引更多的用户&#xff0c;腾讯云经常会推出各种优惠券&#xff0c;让用户在购买云服务时能够享受到更多的优惠&#xff0c;下面给大家整理汇总最新腾讯…

独享静态代理IP在海外市场调研中的独特优势

独享静态代理IP在海外市场调研中扮演着至关重要的角色&#xff0c;提供了一系列无可比拟的优势。独享静态代理IP的稳定性和可靠性对于长期的市场调研至关重要&#xff0c;它保证了连接的持续性和数据的准确性。通过这些方面的综合优势&#xff0c;独享静态代理IP成为海外市场调…

【华为OD机试真题2023CD卷 JAVAJS】矩阵匹配

华为OD2023(C&D卷)机试题库全覆盖,刷题指南点这里 矩阵匹配 知识点二分查找DFS搜索 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 从一个N*M(N<=M)的矩阵中选出N个数,任意两个数字不能在同一行或同一列,求选出来的N个数中第K大的数字的最小值是多少。…