当前位置:主页 > java教程 > Java终止线程实例和stop()方法源码阅读

实例分析Java终止线程和stop()方法

发布:2020-03-16 10:38:32 167


本站收集了一篇Java相关的编程文章,网友国晗昱根据主题投稿了本篇教程内容,涉及到Java、终止线程、stop()、Java终止线程实例和stop()方法源码阅读相关内容,已被349网友关注,下面的电子资料对本篇知识点有更加详尽的解释。

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程序中运用Redis缓存对象的方法

    发布:2022-09-07

    为网友们分享了关于Java的教程,这篇文章主要介绍了在Java程序中运用Redis缓存对象的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧


  • 深入理解java中的null“类型”

    深入理解java中的null“类型”

    发布:2022-10-21

    给网友们整理关于java的教程,这篇文章主要介绍了深入理解java中的null“类型”,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下


  • 如何实现Java日期时间格式转换

    发布:2020-01-14

    这篇文章主要为大家详细介绍了Java日期时间,以及日期相互转换的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下


  • 理解Java指定线程执行顺序(三种方式)

    发布:2020-02-27

    这篇文章主要介绍了Java实现指定线程执行顺序的三种方式,包括通过共享对象锁加上可见变量,通过主线程Join()以及通过线程执行时Join()等三种实现方法,需要的朋友可以参考下


  • Java数据溢出代码详解

    发布:2022-10-09

    给网友们整理关于Java的教程,这篇文章主要介绍了Java数据溢出的相关内容,包括具体代码示例,分析比较详细,希望对大家有所帮助,感兴趣的朋友可以参考下。


  • java中设计模式的实例用法

    发布:2019-11-19

    这篇文章主要介绍了java 中设计模式(值对象)的实例详解的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下


  • Java中File文件操作类的超详细使用教程

    发布:2023-04-25

    File类在包java.io.File下、代表操作系统的文件对象(文件、文件夹),File类提供了诸如:定位文件,获取文件本身的信息、删除文件、创建文件(文件夹)等功能,下面这篇文章主要给大家介绍了关于Java中File文件操作类的超详细使用教程,需要的朋友可以参考下


  • Java面向对象设计原则之迪米特法则介绍

    发布:2023-04-04

    迪米特法则解决类与类之间耦合度问题,如果类A调用了B类的某一个方法,则这两个类就形成了一种紧耦合的方式,当B类这个方法发生变化时,一定会影响A类的执行结果。迪米特法则要求每一个类尽可能少的与其他类发生关系


网友讨论