首页 > 编程语言 >并发编程学习笔记2

并发编程学习笔记2

时间:2024-09-09 10:54:19浏览次数:5  
标签:test1 Thread 编程 笔记 t1 并发 线程 sleep main

1.常见方法

  • join

作用:当某一线程调用该方法时,程序会等待该线程运行结束再执行后续代码

例如

@Slf4j
public class test1 {
    public static void main(String[] args) throws InterruptedException {


        Runnable r = () -> {
            log.info("begin");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            log.info("end");
        };

        Thread t = new Thread(r, "t1");
        t.start();
        t.join();
        log.info("main end...");
    }
}
  •  不加t.join()
16:46:28.691 [t1] INFO com.example.concurent.test.test1 -- begin
16:46:28.691 [main] INFO com.example.concurent.test.test1 -- main end...
16:46:29.695 [t1] INFO com.example.concurent.test.test1 -- end
  • 加t.join()
16:50:30.060 [t1] INFO com.example.concurent.test.test1 -- begin
16:50:31.064 [t1] INFO com.example.concurent.test.test1 -- end
16:50:31.064 [main] INFO com.example.concurent.test.test1 -- main end...

    等待多个结果

        当使用join等待多个线程运行结束时,耗时最长线程的耗时为总耗时。

        例如:t1线程睡眠1000ms,t2线程睡眠2000ms,总耗时为2002ms。

@Slf4j
public class test1 {
    public static void main(String[] args) throws InterruptedException {
        Runnable r1 = () -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        };

        Runnable r2 = () -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        };

        Thread t1 = new Thread(r1, "t1");
        Thread t2 = new Thread(r2, "t2");
        var begin = System.currentTimeMillis();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        var end = System.currentTimeMillis();
        log.info("{}", end - begin);
    }
}

        结果:

16:54:22.116 [main] INFO com.example.concurent.test.test1 -- 2001

        有时效的 join

        可以在调用join方法添加时间参数(单位:毫秒),join如果等待时间超过该参数,则不会继续等待,而是执行后续代码。

  • interrupt

作用:打断线程

        打断sleep的线程:会清空打断状态,并且抛出InterruptedException异常

        打断正常的线程:不会清空打断状态

例如,t1是sleep的线程,t2是正常的线程

@Slf4j
public class test1 {
    public static void main(String[] args) throws InterruptedException {
        Runnable r1 = () -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        };

        Thread t1 = new Thread(r1, "t1");
        t1.start();
        TimeUnit.MILLISECONDS.sleep(500);
        t1.interrupt();
        log.info("{}", t1.isInterrupted());

        Runnable r2 = () -> {
            while (true) {
                var currentThread = Thread.currentThread();
                var interrupted = currentThread.isInterrupted();
                if (interrupted) {
                    log.info("{}", interrupted);
                    break;
                }
            }
        };

        Thread t2 = new Thread(r2, "t2");
        t2.start();
        t2.interrupt();
    }
}

        结果:

Exception in thread "t1" java.lang.RuntimeException: java.lang.InterruptedException: sleep interrupted
	at com.example.concurent.test.test1.lambda$main$0(test1.java:16)
	at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: java.lang.InterruptedException: sleep interrupted
	at java.base/java.lang.Thread.sleep(Native Method)
	at com.example.concurent.test.test1.lambda$main$0(test1.java:14)
	... 1 more
17:17:24.438 [main] INFO com.example.concurent.test.test1 -- false
17:17:24.443 [t2] INFO com.example.concurent.test.test1 -- true

2.两阶段终止模式

        使用interrupt方法设置该线程的打断状态,当该线程读取到打断状态为true或者抛出InterruptedException异常(sleep状态被打断)时,再执行具体打断操作,也就是说,该线程不会真正停止,具体怎么停止由该线程说了算。

例如:

@Slf4j
public class test1 {

    public static void main(String[] args) throws InterruptedException {
        TwoPhaseTermination tpt = new TwoPhaseTermination();
        tpt.start();
        log.info("tpt start");
        Thread.sleep(3500);
        tpt.stop();
    }
}

@Slf4j
class TwoPhaseTermination {

    private Thread monitor;

    //        启动监控线程
    public void start() {
        monitor = new Thread(() -> {
            while (true) {
                Thread thread = Thread.currentThread();
                if (thread.isInterrupted()) {
                    log.info("料理后事");
                    break;
                }
                try {
                    Thread.sleep(1000);
                    log.info("执行监控记录");
                } catch (InterruptedException e) {
                    e.printStackTrace();
//                        重新设置打断标记
                    thread.interrupt();
                }
            }

        });
        monitor.start();
    }

    public void stop() {
        monitor.interrupt();
    }

}

3.守护线程

默认情况下,Java 进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其它非守 护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。

     注意:

  • 垃圾回收器线程就是一种守护线程
  • Tomcat 中的 Acceptor 和 Poller 线程都是守护线程,所以 Tomcat 接收到 shutdown 命令后,不会等 待它们处理完当前请求

标签:test1,Thread,编程,笔记,t1,并发,线程,sleep,main
From: https://blog.csdn.net/Thehao123/article/details/141866005

相关文章

  • HTML笔记 06
    第六章盒子模型border边框border-color:边框颜色border-width:边框粗细border-style:边框样式solid实线dashed虚线dotted点式double双框同时设置边框的颜色·粗细·样式:border:1pxsolid#3a6587margin外边距网页居中对齐margin:auto;padding内边距box-sizin......
  • C++学习笔记(曾经我看不懂的代码2:基于范围的for循环、auto使用、stl容器、template模
    不知不觉c++程序设计:标准库已经看了一大半了,学到了很多,很多曾经在网上和在书上看到却看不懂的代码,在看完标准库中的大半内容以后,都能大致的理清代码的含义。代码模板一:for(auto&a:arr)1、基于范围的for循环:a为迭代变量,arr为迭代范围,&表示引用。写一个例子:#include<ios......
  • 0906, 0909 shell编程与基础算法(leetCode )
    0906哈希表的基本知识:哈希表(HashTable)又称散列表,是除顺序存储结构、链式存储结构和索引表存储结构之外的又一种存储结构。哈希碰撞:解决办法开放定址法:是一类以发生冲突的哈希地址为自变量,通过某种哈希冲突函数得到一个新的空闲的哈希地址的方法。(1)线性探测法从发生......
  • ONCE论文阅读笔记
    ONCE:BoostingContent-basedRecommendationwithBothOpen-andClosed-sourceLargeLanguageModels论文阅读笔记Abstract​ 现有的推荐器在理解项目内容方面面临着巨大挑战。大语言模型(LLM)拥有深层语义理解能力和来自预训练的广泛知识,已被证明在各种自然语言处理任务中非......
  • LeetCode刷题笔记9.2-9.9
    leetCode刷题笔记(9.2-9.9)48.旋转图像(9.3)1)图像即二维数组,图像的旋转本质上是二维数组的旋转变换2)二维数组从外层来看,是若干个子数组的集合,子数组内部维护各自的元素,即若干个row里是row.length个column3)由此可理解下面几个关于二维数组的函数:创建二维数组并初始化int[][]......
  • 【Python学习笔记】 第5章 数值类型
    数值类型基础知识在Python中,数值实际上是一种类型的分类,包括:整数、浮点数复数小数:固定精度对象分数:有理数对象集合:带有数值运算的集合体布尔值:True,False内置函数与块:round,math,random等表达式、无限制精度整数(很大的整数)、位运算、八进制、十二进制、......
  • [oeasy]python0033_先有操作系统还是先有编程语言_c语言是怎么来的
    [趣味拓展]计算机语言起源_c语言诞生......
  • 算法题笔记-滑动窗口
    referdocleetcode对应题目:3.无重复字符的最长子串438.找到字符串中所有字母异位词解题模板://外层循环扩展右边界,内层循环扩展左边界for(intl=0,r=0;r<n;r++){ //当前考虑的元素 while(l<=r&&check()){//扩展左边界 //触发条件,改变滑动......
  • 【编程底层思考】理解控制反转Inverse of Control,IOC 和 依赖注入Dependency Injecti
    RodJohnson是第一个高度重视以配置文件来管理Java实例的协作关系的人,他给这种方式起了一个名字:控制反转(InverseofControl,IOC)。后来MartineFowler为这种方式起了另一个名称:依赖注入(DependencyInjection),因此不管是依赖注入,还是控制反转,其含义完全相同。当某个Java对象(......
  • 编译原理(第3版)上课笔记
    1、编译器是一个程序、具有非常模块化的高层结构离线方式offline2、解释器是一类处理程序的程序在线方式online3、静态计算所生成的目标程序要和源代码语义相同(不能有任何改变)4、动态计算5、编译的各个阶段(1)词法分析器:检查单词是否合法。(2)语法分析器:生成语法树,检......