Java终止线程实例和stop()方法源码阅读

 更新时间:2017年12月29日 15:19:24   作者:Rainmonth  
这篇文章主要介绍了Java终止线程实例和stop()方法源码阅读,具有一定借鉴价值,需要的朋友可以参考下

了解线程

概念

线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。

线程特点

拥有状态,表示线程的状态,同一时刻中,JVM中的某个线程只有一种状态;

·NEW

尚未启动的线程(程序运行开始至今一次未启动的线程)

·RUNNABLE

可运行的线程,正在JVM中运行,但它可能在等待其他资源,如CPU。

·BLOCKED

阻塞的线程,等待某个锁允许它继续运行

·WAITING

无限等待(再次运行依赖于让它进入该状态的线程执行某个特定操作)

·TIMED_WAITING

定时等待(再次运行依赖于让它进入该状态的线程在指定等待时间内某个特定操作)

·TERMINATED

已退出的线程

拥有优先级,决定线程的执行顺序;

1至10之间的整数,默认数值为5。数值越高,执行的几率越高,优先级并不能决定线程的执行顺序。

子线程的优先级默认同父线程的一样。

注意,当以下情况发生时,JVM将停止执行所有线程:

Runtime(运行时)的exit ()方法被调用并且该方法的调用被Security Manager所允许;

所有的“非守护线程”都已停止运行(无论时正常停止还是一场停止);

可以被标记为守护程序(Daemon)

守护线程的子线程仍是守护线程;

守护线程也就是“后台线程”,一般用来执行后台任务,而用户线程一般用户执行用户级任务。

终止线程的方法

1.使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。

当run方法执行完后,线程就会退出。但有时run方法是永远不会结束的。如在服务端程序中使用线程进行监听客户端请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如while循环。如果想让循环永远运行下去,可以使用while(true){……}来处理。但要想使while循环在某一特定条件下退出,最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环是否退出。下面给出了一个利用退出标志终止线程的例子。

FlagExitThread.java

package com.rainmonth;
/**
* Created by RandyZhang on 2017/3/23.
*/
public class FlagExitThread extends Thread {
	public volatile Boolean isExit = false;
	public FlagExitThread(String name) {
		super(name);
	}
	@Override
	  public void run() {
		while (!isExit) {
			System.out.println("I'm running");
		}
	}
}

DemoClient.java

package com.rainmonth;
/**
* Created by RandyZhang on 2017/3/23.
*/
public class DemoClient {
	public static void main(String[] args) {
		System.out.println("优雅的终止线程实例");
		exitByFlag();
		// exitByInterrupt();
	}
	private static void exitByFlag() {
		FlagExitThread flagExitThread = new FlagExitThread(FlagExitThread.class.getSimpleName());
		flagExitThread.start();
		try {
			Thread.sleep(1000);
			flagExitThread.isExit = true;
			flagExitThread.join();
			System.out.println("线程退出");
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	private static void exitByInterrupt() {
		FlagExitThread flagExitThread = new FlagExitThread(FlagExitThread.class.getSimpleName());
		System.out.println("flagExitThread running...");
		flagExitThread.start();
		try {
			Thread.sleep(1500);
			System.out.println("flagExitThread interrupted...");
			flagExitThread.interrupt();
			Thread.sleep(1500);
			System.out.println("stop application...");
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

输出结果:

打印了一大堆I'm running之后线程退出。

2.使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)。

显示调用stop()方法。源码中关于stop() 的描述如下:

/*
* This method is inherently unsafe. Stopping a thread with
* Thread.stop causes it to unlock all of the monitors that it
* has locked (as a natural consequence of the unchecked
* <code>ThreadDeath</code> exception propagating up the stack). If
* any of the objects previously protected by these monitors were in
* an inconsistent state, the damaged objects become visible to
* other threads, potentially resulting in arbitrary behavior. Many
* uses of <code>stop</code> should be replaced by code that simply
* modifies some variable to indicate that the target thread should
* stop running. The target thread should check this variable
* regularly, and return from its run method in an orderly fashion
* if the variable indicates that it is to stop running. If the
* target thread waits for long periods (on a condition variable,
* for example), the <code>interrupt</code> method should be used to
* interrupt the wait.
*/

大意就是说,该方法的不安全性时固有的。调用stop()终止一个线程会释放它已经锁定的所有监视器(这将导致沿堆栈向上传播为检查的ThreadDeath异常被抛出),若此时之前受这些被释放的监视器保护的对象存在不一致性,并且这些对象对其他线程可见,这就会导致一些意想不到的后果。stop操作应该有哪些仅仅只需要修改某些代码就可以指示目标线程应该停止运行的代码来取代(方法一就是这种方式)。如果目标线程由于等待某一条件(如某个条件变量)等待很长时间,我们应该使用interrupt方法来中断该等待(方法三就是这种方式)。

3.使用interrupt方法中断线程。

interrupt字面上是终止的意思,但不要试图通过调用interrupt来终止线程,因为有时即使你调用了该方法,线程仍然会继续执行,可以注释掉上面的exitByFlag(),开启exitByInterrupt() 方法,发现及时调用了interrupt()方法,仍在一直输出I'm running…(不同系统及CPU结果可能有所不同),可见采用interrupt方式也是不安全的。

总结

根据以上的分析,最值得推荐的方式是第一种,我们可以用共享变量(shared variable)的方式来设置标志,并发出信号,通知线程必须终止。当然对这个共享变量的操作我们必须保证是同步的。

以上就是本文关于Java终止线程实例和stop()方法源码阅读的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

相关文章

  • Java getParameter()获取数据为空的问题

    Java getParameter()获取数据为空的问题

    这篇文章主要介绍了Java getParameter()获取数据为空的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Java调用ChatGPT(基于SpringBoot和Vue)实现可连续对话和流式输出的ChatGPT API

    Java调用ChatGPT(基于SpringBoot和Vue)实现可连续对话和流式输出的ChatGPT API

    这篇文章主要介绍了Java调用ChatGPT(基于SpringBoot和Vue),实现可连续对话和流式输出的ChatGPT API(可自定义实现AI助手),文中代码示例介绍的非常详细,感兴趣的朋友可以参考下
    2023-04-04
  • Spring整合消息队列RabbitMQ流程

    Spring整合消息队列RabbitMQ流程

    Spring整合RabbitMQ很容易,但是整合的目的是为了使用,那要使用RabbitMQ就要对其有一定的了解,不然容易整成一团浆糊。因为说到底,Spring只是在封装RabbitMQ的API,让其更容易使用而已,废话不多说,让我们一起整它
    2023-03-03
  • 深入了解集合操作工具Guava Collect

    深入了解集合操作工具Guava Collect

    Guava Collect是Guava工具包中的一个子模块,主要对jdk中的集合操作添加了一些简易的API,同时也是对Collections工具类的扩展。本文将结合实例详细说说它的使用,需要的可以参考一下
    2022-10-10
  • Spring Boot实现简单的定时任务

    Spring Boot实现简单的定时任务

    这篇文章主要给大家介绍了关于利用Spring Boot实现简单的定时任务的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-07-07
  • 通过FeignClient调用微服务提供的分页对象IPage报错的解决

    通过FeignClient调用微服务提供的分页对象IPage报错的解决

    这篇文章主要介绍了通过FeignClient调用微服务提供的分页对象IPage报错的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • eclipse/intellij idea 查看java源码和注释方法

    eclipse/intellij idea 查看java源码和注释方法

    下面小编就为大家带来一篇eclipse/intellij idea 查看java源码和注释方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • MyBatis一级与二级缓存相关配置

    MyBatis一级与二级缓存相关配置

    mybatis-plus是一个Mybatis的增强工具,在Mybatis的基础上只做增强不做改变,为简化开发、提高效率而生,这篇文章带你了解Mybatis的一级和二级缓存
    2023-01-01
  • Java数据结构之简单的连接点(link)实现方法示例

    Java数据结构之简单的连接点(link)实现方法示例

    这篇文章主要介绍了Java数据结构之简单的连接点(link)实现方法,涉及java指针指向节点的相关使用技巧,需要的朋友可以参考下
    2017-10-10
  • SpringMVC常用注解载入与处理方式详解

    SpringMVC常用注解载入与处理方式详解

    这篇文章主要介绍了SpringMVC常用注解载入的方式和处理的方式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09

最新评论