`
wanxiaotao12
  • 浏览: 476274 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java线程中断的本质和编程原则

 
阅读更多

 在历史上,Java试图提供过抢占式限制中断,但问题多多,例如前文介绍的已被废弃的Thread.stop、Thread.suspend和 Thread.resume等。另一方面,出于Java应用代码的健壮性的考虑,降低了编程门槛,减少不清楚底层机制的程序员无意破坏系统的概率。

    如今,Java的线程调度不提供抢占式中断,而采用协作式的中断。其实,协作式的中断,原理很简单,就是轮询某个表示中断的标记,我们在任何普通代码的中都可以实现。 例如下面的代码:

    volatile bool isInterrupted;

    //…

    while(!isInterrupted) {

        compute();

    }

    但是,上述的代码问题也很明显。当compute执行时间比较长时,中断无法及时被响应。另一方面,利用轮询检查标志变量的方式,想要中断wait和sleep等线程阻塞操作也束手无策

    如果仍然利用上面的思路,要想让中断及时被响应,必须在虚拟机底层进行线程调度的对标记变量进行检查。是的,JVM中确实是这样做的。下面摘自java.lang.Thread的源代码:

        public static boolean interrupted() {
            return currentThread().isInterrupted(true);
        }

       //…

        private native boolean isInterrupted(boolean ClearInterrupted);

    可以发现,isInterrupted被声明为native方法,取决于JVM底层的实现。

    实际上,JVM内部确实为每个线程维护了一个中断标记但应用程序不能直接访问这个中断变量,必须通过下面几个方法进行操作:
    public class Thread {
        //设置中断标记
        public void interrupt() { ... }  
        //获取中断标记的值
        public boolean isInterrupted() { ... }
        //清除中断标记,并返回上一次中断标记的值
        public static boolean interrupted() { ... }   
        ...
    }

    通常情况下,调用线程的interrupt方法,并不能立即引发中断,只是设置了JVM内部的中断标记。因此,通过检查中断标记,应用程序可以做一些特殊操作,也可以完全忽略中断。
    
    你可能想,如果JVM只提供了这种简陋的中断机制,那和应用程序自己定义中断变量并轮询的方法相比,基本也没有什么优势。
    
    JVM内部中断变量的主要优势,就是对于某些情况,提供了模拟自动“中断陷入”的机制。
    
    在执行涉及线程调度的阻塞调用时(例如wait、sleep和join),如果发生中断,被阻塞线程会“尽可能快的”抛出InterruptedException。因此,我们就可以用下面的代码框架来处理线程阻塞中断:
    try {
        //wait、sleep或join
    }
    catch(InterruptedException e) {
        //某些中断处理工作
    }
    所谓“尽可能快”,我猜测JVM就是在线程调度调度的间隙检查中断变量,速度取决于JVM的实现和硬件的性能。    

    然而,对于某些线程阻塞操作,JVM并不会自动抛出InterruptedException异常。例如,某些I/O操作和内部锁操作。对于这类操作,可以用其他方式模拟中断:
    1)java.io中的异步socket I/O
    读写socket的时候,InputStream和OutputStream的read和write方法会阻塞等待,但不会响应java中断。不过,调用Socket的close方法后,被阻塞线程会抛出SocketException异常。
    
    2)利用Selector实现的异步I/O
    如果线程被阻塞于Selector.select(在java.nio.channels中),调用wakeup方法会引起ClosedSelectorException异常。
    
    3)锁获取
    如果线程在等待获取一个内部锁,我们将无法中断它。但是,利用Lock类的lockInterruptibly方法,我们可以在等待锁的同时,提供中断能力。
    
    
    另外,在任务与线程分离的框架中,任务通常并不知道自身会被哪个线程调用,也就不知道调用线程处理中断的策略。所以,在任务设置了线程中断标记后,并不能确保任务会被取消。因此,有以下两条编程原则:
    1)除非你知道线程的中断策略,否则不应该中断它。
        这条原则告诉我们,不应该直接调用Executer之类框架中线程的interrupt方法,应该利用诸如Future.cancel的方法来取消任务。
    
    2)任务代码不该猜测中断对执行线程的含义。
        这条原则告诉我们,一般代码遇在到InterruptedException异常时,不应该将其捕获后“吞掉”,而应该继续向上层代码抛出。
        
    总之,Java中的非抢占式中断机制,要求我们必须改变传统的抢占式中断思路,在理解其本质的基础上,采用相应的原则和模式来编程。

 

http://blog.csdn.net/dlite/article/details/4218105

分享到:
评论

相关推荐

    深入Java线程中断的本质与编程原则的概述

    本文将深入探讨Java线程中断的本质以及编程原则。 首先,理解线程中断的本质。Java线程中断并不意味着强制停止一个线程,而是设置了一个中断标志,这个标志是JVM内部维护的。通过`Thread.interrupt()`方法,我们...

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第一阶段27讲、wait和sleep的本质区别是什么,深入分析(面试常见问题).mp4 │ 高并发编程第一阶段28讲、线程生产者消费者的综合实战结合Java8语法.mp4 │ 高并发编程第一阶段29讲、如何实现一个...

    java多线程编程总结.pdf

    在多线程编程中,Java 提供了丰富的API和机制来处理线程的创建、管理、同步以及线程间的通信。下面将详细总结Java多线程编程的关键知识点。 首先,Java 中实现线程的方法主要有两种:一种是继承Thread类,另一种是...

    java线程学习笔记

    Java线程有五种基本状态:新建、就绪、运行、阻塞和终止。 1. **新建状态**:当使用`new`关键字创建了一个`Thread`实例后,该线程处于新建状态。 2. **就绪状态**:调用`start()`方法后,线程进入就绪状态,等待CPU...

    JAVA教程之线程篇

    深入理解Java线程前,需澄清几个关键术语: 1. **Java**:起初被视为一种编程语言,但发展至今,Java已演变成一个全面的平台,由编程语言、API和虚拟机规范三部分构成。线程特性贯穿于Java平台的每一个层面,确保了...

    javaduoxiancheng.rar_多线程 java

    "javaduoxiancheng.rar_多线程 java"这个压缩包文件可能包含了关于Java多线程编程的相关资料和示例代码,帮助开发者深入理解和实践Java的多线程同步机制。 首先,我们需要了解Java中线程的创建方式。Java提供了两种...

    汪文君高并发编程实战视频资源全集

    │ 高并发编程第一阶段27讲、wait和sleep的本质区别是什么,深入分析(面试常见问题).mp4 │ 高并发编程第一阶段28讲、线程生产者消费者的综合实战结合Java8语法.mp4 │ 高并发编程第一阶段29讲、如何实现一个...

    Java多线程教程吐血整理干货.md

    这些方法提供了管理线程中断的有效机制,可以帮助避免因线程无法响应中断请求而导致的问题。 以上这些概念和方法是Java多线程编程的基础,了解它们对于设计高性能、健壮的应用程序至关重要。通过合理地利用多线程的...

    java_concurrency_in_practice_source源代码

    9. **中断和异常处理**:Java允许线程中断,通过`Thread.interrupt()`方法实现。源码将展示如何响应中断请求,以及正确处理线程中断时抛出的`InterruptedException`。 10. **并发工具类**:`CountDownLatch`、`...

    Java并发编程最全面试题 123道

    总的来说,Java并发编程是一门深奥的学问,需要深入理解线程的本质、并发模型、同步机制以及性能优化策略,才能编写出高效、稳定的并发程序。在面试或实际工作中,熟练掌握这些知识点对于提升软件系统的性能和可靠性...

    java并发编程笔记

    在Java中,通过合理利用线程和同步机制可以实现并发编程。 #### 五、线程状态 Java中的线程主要有以下几种状态: - **NEW**: 新建状态 - **RUNNABLE**: 可运行状态 - **BLOCKED**: 阻塞状态 - **WAITING**: 等待...

    Java并发编程面试题合集.pdf

    在 Java 中守护线程和本地线程的区别? - **守护线程**:在 Java 中,守护线程(Daemon Thread)是一种特殊的后台线程,它不会阻止程序的关闭。当所有非守护线程结束运行后,Java 虚拟机将会退出。守护线程主要...

    java基本教程之线程休眠 java多线程教程

    在Java编程语言中,线程是并发执行的基本单元。多线程使得程序可以在同一时间处理多个任务,提高系统效率。本文将深入讲解`sleep()`方法,这是Java中控制线程休眠的重要工具。 1. `sleep()`介绍 `sleep()`方法位于`...

    Java基础学习59.pdf

    Java线程生命周期包括以下状态:新建(New)、可运行(Runnable)、阻塞(Blocked)、等待(Waiting)、超时等待(Timed Waiting)和终止(Terminated)。创建线程后,通过调用start()方法进入可运行状态。线程执行...

    艾编程coding老师:JUC 并发编程 + 底层原理.pdf

    JUC中的并发编程主要涉及到线程的状态,Java线程有六种状态,分别是NEW(新建)、RUNNABLE(可运行)、BLOCKED(阻塞)、WAITING(等待)、TIMED_WAITING(超时等待)和TERMINATED(终止)。理解这些线程状态是深入...

    Java编程思想笔记(全)

    ### Java编程思想笔记知识点概述 #### 第 1 章 对象导论 在这一章节中,主要介绍...以上内容概括了《Java编程思想笔记》中的核心知识点,涵盖了Java语言的基础到高级特性,适合初学者和有一定经验的开发者参考学习。

    22-线程间通信和Android多线程1

    线程间通信是多线程编程中的重要概念,特别是在Android应用开发中,由于其独特的UI更新机制,使得线程间的协作和通信变得尤为关键。在Android中,主线程(UI线程)负责处理用户交互,而其他工作线程通常用于执行耗时...

    java基于TCP的简单聊天室

    Java基于TCP的简单聊天室是一种使用Java编程语言构建的基础网络通信应用,主要利用TCP(传输控制协议)来实现客户端和服务器之间的实时交互。TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,它确保了...

    java sleep()和wait()

    虽然`sleep()`和`wait()`都可以使线程进入等待状态,但它们之间存在本质的区别: 1. **锁资源的释放**:`sleep()`不会释放任何锁资源,而`wait()`则会释放当前对象的锁。 2. **线程的唤醒**:`sleep()`方法的线程在...

    Java下载器 用 Java 编写的URL下载器 workspace

    【Java下载器 用 Java 编写的URL下载器 workspace】是一个项目,主要目的是实现一个基于Java编程语言的URL资源下载工具。这个项目的工作空间包含了相关的源代码和可能的配置文件,便于开发者理解和学习如何利用Java...

Global site tag (gtag.js) - Google Analytics