我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java线程生命周期的终止与复位怎么实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java线程生命周期的终止与复位怎么实现

这篇文章主要介绍“Java线程生命周期的终止与复位怎么实现”,在日常操作中,相信很多人在Java线程生命周期的终止与复位怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java线程生命周期的终止与复位怎么实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

Thread生命周期

生命周期概述

Java的线程状态描述放在Thread类里面的枚举类State中.总共包含了6中状态(从出生到死亡)。

public enum State {        NEW,        RUNNABLE,        BLOCKED,        WAITING,        TIMED_WAITING,        TERMINATED;}

线程生命周期流程图

Java线程生命周期的终止与复位怎么实现

线程生命周期测试

public class ThreadStatusDemo {    public static void main(String[] args) throws InterruptedException {        // 测试 NEW RUNNABLE TERMINATED        Thread terminated_thread = new Thread(() -> {            long start = System.currentTimeMillis();            // 运行三秒 ,打印TERMINATED_THREAD线程runnable状态            while (System.currentTimeMillis()-start<3000){}        }, "TERMINATED_THREAD");        // NEW        Thread.State state = terminated_thread.getState();        System.out.println(terminated_thread.getName()+" :state = " + state);        terminated_thread.start();        TimeUnit.SECONDS.sleep(1);        // RUNNABLE        Thread.State state1 = terminated_thread.getState();        System.out.println(terminated_thread.getName()+"state1 = " + state1);        TimeUnit.SECONDS.sleep(5);        Thread.State state2 = terminated_thread.getState();        // TERMINATED        System.out.println(terminated_thread.getName()+"state2 = " + state2);        // RUNNABLE        new Thread(() -> {            while (true) {            }        }, "Runnle_Thread").start();        // TIMED_WAITING        new Thread(() -> {            while (true) {                try {                    TimeUnit.SECONDS.sleep(1);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }, "Time_Waiting_Thread").start();        // WAITING        new Thread(() -> {            while (true) {                synchronized (ThreadStatusDemo.class) {                    try {                        ThreadStatusDemo.class.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }, "Waiting_Thread").start();        // 这两个看谁先抢占到cpu获得锁,另一个就blocked        // timed_waiting        new Thread(new BlockedDemo(), "Blocke01_Thread").start();        // blocked        new Thread(new BlockedDemo(), "Blocke02_Thread").start();    }    static class BlockedDemo extends Thread {        @Override        public void run() {            synchronized (BlockedDemo.class) {                while (true) {                    try {                        TimeUnit.SECONDS.sleep(100);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }    }}

Java线程生命周期的终止与复位怎么实现

Java线程生命周期的终止与复位怎么实现

启动线程

java中的启动

Java启动一个线程调用start方法,start方法内部调用了 start0()native方法。

public synchronized void start() {    . . .    boolean started = false;    try {         // 调用native方法        start0();        started = true;    } finally {        try {            if (!started) {                group.threadStartFailed(this);            }        } catch (Throwable ignore) {                    }    }}

这个测试是为了验证上图的正确性,只贴了部分.

Hotspot中的启动

查看指引:

Java线程生命周期的终止与复位怎么实现

 在jvm.cpp找到JVM_StartThread方法。发现是先创建个 JavaThread作为本地线程然后启动这个本地线程(借助os【thread.cpp】,因为jvm是跨平台的,这里是以linux-os为示例)

JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))  JVMWrapper("JVM_StartThread");  JavaThread *native_thread = NULL;  bool throw_illegal_thread_state = false;  {    MutexLocker mu(Threads_lock);    if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {      throw_illegal_thread_state = true;    } else {      jlong size =             java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));      size_t sz = size > 0 ? (size_t) size : 0;      // 先创建一个JavaThread      native_thread = new JavaThread(&thread_entry, sz);      if (native_thread->osthread() != NULL) {        native_thread->prepare(jthread);      }    }  }  if (throw_illegal_thread_state) {    THROW(vmSymbols::java_lang_IllegalThreadStateException());  }  assert(native_thread != NULL, "Starting null thread?");  if (native_thread->osthread() == NULL) {    delete native_thread;    if (JvmtiExport::should_post_resource_exhausted()) {      JvmtiExport::post_resource_exhausted(        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS,        "unable to create new native thread");    }    THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),              "unable to create new native thread");  }  // 然后启动这个本地线程 thread.cpp  Thread::start(native_thread);JVM_END

JavaThread 创建线程:

JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :  Thread()#if INCLUDE_ALL_GCS  , _satb_mark_queue(&_satb_mark_queue_set),  _dirty_card_queue(&_dirty_card_queue_set)#endif // INCLUDE_ALL_GCS{  if (TraceThreadEvents) {    tty->print_cr("creating thread %p", this);  }  initialize();  _jni_attach_state = _not_attaching_via_jni;  set_entry_point(entry_point);  os::ThreadType thr_type = os::java_thread;  thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread :                                                     os::java_thread// 调用os(操作系统)创建个线程  os::create_thread(this, thr_type, stack_sz);  _safepoint_visible = false;   . . .}

thread.cpp 启动线程:

// tips: 启动线程的方法void Thread::start(Thread* thread) {  trace("start", thread);  // Start is different from resume in that its safety is guaranteed by context or  // being called from a Java method synchronized on the Thread object.  if (!DisableStartThread) {    if (thread->is_Java_thread()) {      // Initialize the thread state to RUNNABLE before starting this thread.      // Can not set it after the thread started because we do not know the      // exact thread state at that time. It could be in MONITOR_WAIT or      // in SLEEPING or some other state.      // tips:启动之后设置线程的状态为 可运行状态 RUNNABLE      java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(),                                          java_lang_Thread::RUNNABLE);    }    // 借助操作系统启动线程    os::start_thread(thread);  }}

线程中断与复位

不要使用stop方法

线程的终止不要简单的调用 stop方法,这个方法和其他的线程控制方法(suspend,resume)一样都是过期了不建议使用的,这些方法都是不安全的。 例如stop()方法在结束一个线程的时候并不保证线程资源的正常释放,因此可能导致出现一些不确定的状态。 按照人类逻辑来理解:T1线程调用方法修改T2线程的状态,但是T2现在在做什么T1是不清楚的,所以强制他关闭就是不安全的,就好比在Linux中使用 kill -9 杀掉一个进程。

使用interrupt方法

interrupt()方法只是修改了被中断线程的中断标志 ,并没有做什么过分的事儿。就像平时写代码的时候修改某对象的标志,对象自己通过标志类决定执行什么逻辑。这里也是一样,interrupt()方法修改中断标志,被中断的线程,自己决定做什么事儿(中断或者不中断都是被中断线程自己决定的,外部只是通知他,不是强迫他)。追一下源码。

Java调用interrupt方法 

Java线程生命周期的终止与复位怎么实现

通过指引找到 jvm.cpp#JVM_Interrupt方法

Java线程生命周期的终止与复位怎么实现

thread.cpp interrupt 借用操作系统。直接通过系统调用 interruptvoid Thread::interrupt(Thread* thread) {  trace("interrupt", thread);  debug_only(check_for_dangling_thread_pointer(thread);)  // tips: 调用操作系统的interrupt方法  os::interrupt(thread);}

这里还是以os_linux.cpp为例最终调用osthread的set_interrupted修改状态 

Java线程生命周期的终止与复位怎么实现

Java线程生命周期的终止与复位怎么实现

这里就印证了上方的 Thread.interrupt()只是修改了线程的一个标志位 ,并没有做什么过分的事儿。

线程的复位

interruptedisInterrupted

这两个放在一起是因为他们底层都是调用的同一个native方法isInterrupted()只是给了不同的入参。 再就是,有过面试官问到他两的区别,所以干脆放在一起。首先说结论 ,isInterrupted()会返回线程的中断状态,interrupted()不仅会返回中断状态,而且如果线程处于状态状态还会将线程终端状态复位(清除中断状态)。

Java线程生命周期的终止与复位怎么实现

Java线程生命周期的终止与复位怎么实现

Java线程生命周期的终止与复位怎么实现

Java线程生命周期的终止与复位怎么实现

os_linux.cpp的is_interrupted()方法印证了上面说的isInterrupted()会返回线程的中断状态,interrupted()不仅会返回中断状态,而且如果线程处于状态状态还会将线程终端状态复位(清除中断状态)。

其他的线程复位

Java中只要抛出了InnterruptException异常的方法都对线程进行了复位。先理顺下为什么要这么做:查看下基本上抛出InnterruptException异常的方法都是线程阻塞方法,比如sleep(),wait(),join()。这类方法执行后线程会处于TIMED_WAITING或者WAITING状态,处于这类状态的线程是不受控的(线程丧失了对自己的主导,需要其他的线程唤醒,或者阻塞时间到达才能拥有自己的主导权),这个时候线程中断,线程自己却没办法处理。甚至可能永远等不到释放而无法执行中断。所以,在线程是中断状态下,执行方法让线程阻塞,就要抛出一个异常告诉外界 ,我现在是阻塞状态,并且将中断标记复位,方便外界进行处理(例如中断线程的执行或者继续阻塞方法),相当于给了外界一个改变线程状态的入口。 以sleep()为例追踪下源码:

Java线程生命周期的终止与复位怎么实现

通过指引找到 jcm.cpp#JVM_Sleep

Java线程生命周期的终止与复位怎么实现

方法入口就直接判断线程的中断状态了 ,is_interrupted()上面介绍过了,参数为true就是清除中断标志并且返回清除之前的中断状态。这里线程是中断状态的就直接抛出 InnterruptException sleep interrupted异常了。

到此,关于“Java线程生命周期的终止与复位怎么实现”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java线程生命周期的终止与复位怎么实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java线程生命周期的终止与复位怎么实现

这篇文章主要介绍“Java线程生命周期的终止与复位怎么实现”,在日常操作中,相信很多人在Java线程生命周期的终止与复位怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java线程生命周期的终止与复位怎
2023-07-02

Java线程的6种状态与生命周期是什么

本文小编为大家详细介绍“Java线程的6种状态与生命周期是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java线程的6种状态与生命周期是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1.线程状态(生命
2023-06-30

Java项目中如何实现控制线程的生命周期

Java项目中如何实现控制线程的生命周期?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。一、线程的生命周期线程状态转换图:1、新建状态用new关键字和Thread
2023-05-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录