java并发原理实战(3) -- 线程的中断和初始化

简介: java并发原理实战(3) -- 线程的中断和初始化

1.多线程中start和run方法的区别?



start源码:

1dc618a0ed9580ce8bfa6facb208c08f.png


1。start():


先来看看Java API中对于该方法的介绍:


使该线程开始执行;Java 虚拟机调用该线程的 run 方法。


结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法)。


多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。


用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体中的代码执行完毕而直接继续执行后续的代码。通过调用Thread类的 start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里的run()方法 称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。


2。run():


同样先看看Java API中对该方法的介绍:


如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。


Thread 的子类应该重写该方法。


run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。


3。总结:


调用start方法方可启动线程,而run方法只是thread类中的一个普通方法调用,还是在主线程里执行。


2.Thread.currentThread()与this的区别


在自定义线程类时,如果线程类是继承java.lang.Thread的话,那么线程类就可以使用this关键字去调用继承自父类Thread的方法,this就是当前的对象。


另一方面,Thread.currentThread()可以获取当前线程的引用,一般都是在没有线程对象又需要获得线程信息时通过Thread.currentThread()获取当前代码段所在线程的引用。


3.后台进程setDaemon有啥用


设置守护线程 其他线程执行完,即使他自己没有执行完,他也会退出


演示1:


1dc618a0ed9580ce8bfa6facb208c08f.png5d4c6812c8535adbb050f4ddf2e1bce8.png


运行结果:

46a9d80a6e05e4e3b19d57a0ee70bcdf.png


把demo2的代码放开:

66ba272a0bfc97be54a5fa679e3d5482.png


看下结果:

88b9988b40447cb37c7e3c492d49867f.png


结果显示: 一直在执行,说明一个问题。demo1守护着demo2在运行,如果没有别的线程在运行他也得死掉。这保镖很敬业!!


4.线程的中断


①暴力停止stop(不建议使用)


1dc618a0ed9580ce8bfa6facb208c08f.png


2秒后,线程停止:


5d4c6812c8535adbb050f4ddf2e1bce8.png


为啥不推荐:


原因:


①:直接给退出线程了,那我一直用的资源得不到释放

②:释放锁,造成数据不一致。


原因1示例:


46a9d80a6e05e4e3b19d57a0ee70bcdf.png


原因二实例:



66ba272a0bfc97be54a5fa679e3d5482.png

1dc618a0ed9580ce8bfa6facb208c08f.png


②通过中断标志中断(推荐)


这里java设计的api,三个反人类的方法:


5d4c6812c8535adbb050f4ddf2e1bce8.png


傻傻分不清楚:


interrupt(): 实例对象方法

46a9d80a6e05e4e3b19d57a0ee70bcdf.png


interrupted 静态方法: 这相当于一个 测试方法,测试一下,当前的线程是 中断的线程吗?测试完事后,将当前行线程的中断标志改为false。


66ba272a0bfc97be54a5fa679e3d5482.png88b9988b40447cb37c7e3c492d49867f.png


isInterrupted


isTnterrupted:普通方法,也是一个测试方法,看下调用的对象是中断了吗?和上面不同的是,他不清除中断标志。原来中断标志是啥还是啥。


1dc618a0ed9580ce8bfa6facb208c08f.png


③中断线程推荐写法:使用三个反人类的方法+抛出异常方方式


代码演示:

5d4c6812c8535adbb050f4ddf2e1bce8.png

运行结果:

46a9d80a6e05e4e3b19d57a0ee70bcdf.png


说明: 线程1被清除了。


这算是中断线程最好的方式,更多可以看下《java多线程核心技术》这本书,里面还有沉睡的线程停止,异常方法停止也就是现在说的,还有3个反人类方法+return方式,但是最好的这里说了。


5.暂停线程(不推荐使用)


过时的方法,不说也可以,但是看到以前的代码还是需要了解下的:

1dc618a0ed9580ce8bfa6facb208c08f.png


不推荐使用的原因:


①独占资源:


5d4c6812c8535adbb050f4ddf2e1bce8.png


独占资源的情况1:

46a9d80a6e05e4e3b19d57a0ee70bcdf.png


运行结果:

1dc618a0ed9580ce8bfa6facb208c08f.png


独占资源的情况2(使用print的时候):

5d4c6812c8535adbb050f4ddf2e1bce8.png

结果显示:没问题,线程被暂停了,没机会执行了,main方法退出了也就。接下来,变下

46a9d80a6e05e4e3b19d57a0ee70bcdf.png

66ba272a0bfc97be54a5fa679e3d5482.png


②不同步


1dc618a0ed9580ce8bfa6facb208c08f.png5d4c6812c8535adbb050f4ddf2e1bce8.png


6.线程初始化


看下线程的几个构造方法

46a9d80a6e05e4e3b19d57a0ee70bcdf.png


点看会看到


1dc618a0ed9580ce8bfa6facb208c08f.png

5d4c6812c8535adbb050f4ddf2e1bce8.png46a9d80a6e05e4e3b19d57a0ee70bcdf.png


private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }
        this.name = name;
        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */
            /* If there is a security manager, ask the security manager
               what to do. */
            if (security != null) {
                g = security.getThreadGroup();
            }
            /* If the security doesn't have a strong opinion of the matter
               use the parent thread group. */
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }
        /* checkAccess regardless of whether or not threadgroup is
           explicitly passed in. */
        g.checkAccess();
        /*
         * Do we have the required permissions?
         */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }
        g.addUnstarted();
        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;
        /* Set thread ID */
        tid = nextThreadID();
    }


全部调用的都是init方法,干了啥呢?


1)创建你的线程,就是你的父线程

2)默认的ThreadGroup就是父线程的ThreadGroup

3)默认的daemon状态是父线程的daemon状态

4)默认的优先级是父线程的优先级

5)默认的线程名称是Thread-X的形式

6)线程id是从1开始的全局递增。



相关文章
|
13天前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
134 60
【Java并发】【线程池】带你从0-1入门线程池
|
5天前
|
存储 缓存 安全
【原理】【Java并发】【volatile】适合初学者体质的volatile原理
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是写出高端的CRUD应用。2025年,我正在沉淀自己,博客更新速度也在加快。在这里,我会分享关于Java并发编程的深入理解,尤其是volatile关键字的底层原理。 本文将带你深入了解Java内存模型(JMM),解释volatile如何通过内存屏障和缓存一致性协议确保可见性和有序性,同时探讨其局限性及优化方案。欢迎订阅专栏《在2B工作中寻求并发是否搞错了什么》,一起探索并发编程的奥秘! 关注我,点赞、收藏、评论,跟上更新节奏,让我们共同进步!
73 8
【原理】【Java并发】【volatile】适合初学者体质的volatile原理
|
2天前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
46 23
|
9天前
|
Java 调度
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
当我们创建一个`ThreadPoolExecutor`的时候,你是否会好奇🤔,它到底发生了什么?比如:我传的拒绝策略、线程工厂是啥时候被使用的? 核心线程数是个啥?最大线程数和它又有什么关系?线程池,它是怎么调度,我们传入的线程?...不要着急,小手手点上关注、点赞、收藏。主播马上从源码的角度带你们探索神秘线程池的世界...
67 0
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
|
25天前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
98 14
|
1月前
|
安全 Java 程序员
Java 面试必问!线程构造方法和静态块的执行线程到底是谁?
大家好,我是小米。今天聊聊Java多线程面试题:线程类的构造方法和静态块是由哪个线程调用的?构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节有助于掌握Java多线程机制。下期再见! 简介: 本文通过一个常见的Java多线程面试题,详细讲解了线程类的构造方法和静态块是由哪个线程调用的。构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节对掌握Java多线程编程至关重要。
54 13
|
1月前
|
安全 Java 开发者
【JAVA】封装多线程原理
Java 中的多线程封装旨在简化使用、提高安全性和增强可维护性。通过抽象和隐藏底层细节,提供简洁接口。常见封装方式包括基于 Runnable 和 Callable 接口的任务封装,以及线程池的封装。Runnable 适用于无返回值任务,Callable 支持有返回值任务。线程池(如 ExecutorService)则用于管理和复用线程,减少性能开销。示例代码展示了如何实现这些封装,使多线程编程更加高效和安全。
|
1月前
|
存储 算法 Java
【JAVA】生成accessToken原理
在Java中,生成accessToken用于身份验证和授权,确保合法用户访问受保护资源。流程包括:1. 身份验证(如用户名密码、OAuth 2.0);2. 生成唯一且安全的令牌;3. 设置令牌有效期并存储;4. 客户端传递令牌,服务器验证其有效性。常见场景为OAuth 2.0协议,涉及客户端注册、用户授权、获取授权码和换取accessToken。示例代码展示了使用Apache HttpClient库模拟OAuth 2.0获取accessToken的过程。
|
2月前
|
存储 Java C++
Java数组:静态初始化与动态初始化详解
本文介绍了Java中数组的定义、特点及初始化方式。
100 12
|
2月前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
123 17

热门文章

最新文章