`
king_tt
  • 浏览: 2110841 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Java中的线程Thread方法之---stop()

 
阅读更多

搞过Java线程的人都知道,stop这个方法是臭名昭著了,早就被弃用了,但是现在任然有很多钟情与他的人,永远都放不下他,因为从他的字面意思上我们可以知道他貌似可以停止一个线程,这个需求是每个搞线程开发的人都想要的操作,但是他并非是真正意义上的停止线程,而且停止线程还会引来一些其他的麻烦事,下面就来详细的介绍一下这个方法的历史:


从SUN的官方文档可以得知,调用Thread.stop()方法是不安全的,这是因为当调用Thread.stop()方法时,会发生下面两件事:

1. 即刻抛出ThreadDeath异常,在线程的run()方法内,任何一点都有可能抛出ThreadDeath Error,包括在catch或finally语句中。

2. 会释放该线程所持有的所有的锁,而这种释放是不可控制的,非预期的。

当线程抛出ThreadDeath异常时,会导致该线程的run()方法突然返回来达到停止该线程的目的。ThreadDetath异常可以在该线程run()方法的任意一个执行点抛出。但是,线程的stop()方法一经调用线程的run()方法就会即刻返回吗?

  1. packagecom.threadstop.demo;
  2. publicclassThreadStopTest{
  3. publicstaticvoidmain(String[]args){
  4. try{
  5. Threadt=newThread(){
  6. //对于方法进行了同步操作,锁对象就是线程本身
  7. publicsynchronizedvoidrun(){
  8. try{
  9. longstart=System.currentTimeMillis();
  10. //开始计数
  11. for(inti=0;i<100000;i++)
  12. System.out.println("runing.."+i);
  13. System.out.println((System.currentTimeMillis()-start)+"ms");
  14. }catch(Throwableex){
  15. System.out.println("Caughtinrun:"+ex);
  16. ex.printStackTrace();
  17. }
  18. }
  19. };
  20. //开始计数
  21. t.start();
  22. //主线程休眠100ms
  23. Thread.sleep(100);
  24. //停止线程的运行
  25. t.stop();
  26. }catch(Throwablet){
  27. System.out.println("Caughtinmain:"+t);
  28. t.printStackTrace();
  29. }
  30. }
  31. }
运行结果如下:


由于打印的数据太多了,就没有全部截图了,但是我们可以看到,调用了stop方法之后,线程并没有停止,而是将run方法执行完。那这个就诡异了,多次运行之后发现每次运行的结果都表明,工作线程并没有停止,而是每次都成功的数完数(执行完run方法),然后正常中止,而不是由stop()方法进行终止的。这个是为什么呢?根据SUN的文档,原则上只要一调用thread.stop()方法,那么线程就会立即停止,并抛出ThreadDeath error,查看了Thread的源代码后才发现,原先Thread.stop(Throwable obj)方法是同步的,而我们工作线程的run()方法也是同步,那么这样会导致主线程和工作线程共同争用同一个锁(工作线程对象本身),由于工作线程在启动后就先获得了锁,所以无论如何,当主线程在调用t.stop()时,它必须要等到工作线程的run()方法执行结束后才能进行,结果导致了上述奇怪的现象。

下面看一下stop的源码:

  1. @Deprecated
  2. publicfinalvoidstop(){
  3. stop(newThreadDeath());
  4. }
再进到stop看:

  1. @Deprecated
  2. publicfinalsynchronizedvoidstop(Throwableobj){
  3. if(obj==null)
  4. thrownewNullPointerException();
  5. SecurityManagersecurity=System.getSecurityManager();
  6. if(security!=null){
  7. checkAccess();
  8. if((this!=Thread.currentThread())||
  9. (!(objinstanceofThreadDeath))){
  10. security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
  11. }
  12. }
  13. //Azerostatusvaluecorrespondsto"NEW",itcan'tchangeto
  14. //not-NEWbecauseweholdthelock.
  15. if(threadStatus!=0){
  16. resume();//Wakeupthreadifitwassuspended;no-opotherwise
  17. }
  18. //TheVMcanhandleallthreadstates
  19. stop0(obj);
  20. }
stop0(obj)是一个native方法,我们看到stop方法是同步的,而这个同步的锁对象正好也是线程本身,所以造成上面的现象。

把上述工作线程的run()方法的同步去掉,再进行执行,结果就如上述第一点描述的那样了,运行结果如下:


从结果中我们可以看到,调用stop方法会抛出一个ThreadDeath异常,这时候run方法也就执行结束了,线程就终止了,这种是用抛异常来结束线程的,但是这种抛出线程是不安全的,因为他不可控制,不知道到在run方法中的何处就可能抛出异常,所以是危险的。下面在看一下stop的这个隐患可能造成的影响:


接下来是看看当调用thread.stop()时,被停止的线程会不会释放其所持有的锁,看如下代码:

  1. publicstaticvoidmain(String[]args){
  2. <spanstyle="white-space:pre"></span>//定义锁对象
  3. finalObjectlock=newObject();
  4. //定义第一个线程,首先该线程拿到锁,而后等待3s,之后释放锁
  5. try{
  6. Threadt0=newThread(){
  7. publicvoidrun(){
  8. try{
  9. synchronized(lock){
  10. System.out.println("thread->"+getName()+"acquirelock.");
  11. sleep(3*1000);
  12. System.out.println("thread->"+getName()+"等待3s");
  13. System.out.println("thread->"+getName()+"releaselock.");
  14. }
  15. }catch(Throwableex){
  16. System.out.println("Caughtinrun:"+ex);
  17. ex.printStackTrace();
  18. }
  19. }
  20. };
  21. //定义第二个线程,等待拿到锁对象
  22. Threadt1=newThread(){
  23. publicvoidrun(){
  24. synchronized(lock){
  25. System.out.println("thread->"+getName()+"acquirelock.");
  26. }
  27. }
  28. };
  29. //线程一先运行,先拿到lock
  30. t0.start();
  31. //而后主线程等待100ms,为了做延迟
  32. Thread.sleep(100);
  33. //停止线程一
  34. //t0.stop();
  35. //这时候在开启线程二
  36. t1.start();
  37. }catch(Throwablet){
  38. System.out.println("Caughtinmain:"+t);
  39. t.printStackTrace();
  40. }
  41. }

运行结果如下:


从运行结果中我们可以看到,当没有进行t0.stop()方法的调用时, 可以发现,两个线程争用锁的顺序是固定的。这个现象是正常的。


下面我们把t0.stop注释的哪行,删除注释,调用t0.stop()方法,运行结果如下:


从运行结果中我们可以看到,调用了t0.stop()方法后,可以发现,t0线程抛出了ThreadDeath error并且t0线程释放了它所占有的锁。


从上面的程序验证结果来看,thread.stop()确实是不安全的。它的不安全主要是:释放该线程所持有的所有的锁。一般任何进行加锁的代码块,都是为了保护数据的一致性,如果在调用thread.stop()后导致了该线程所持有的所有锁的突然释放(不可控制),那么被保护数据就有可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。


下面顺便说一下:

Java中多线程锁释放的条件:

1)执行完同步代码块,就会释放锁。(synchronized)
2)在执行同步代码块的过程中,遇到异常而导致线程终止,锁也会被释放。(exception)
3)在执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程会释放锁,进入对象的等待池。(wait)

从上面的三点我就可以看到stop方法释放锁是在第二点的,通过抛出异常来释放锁,通过证明,这种方式是不安全的,不可靠的。


好吧,Thread中的stop方法就说到这里了,后续还会有关Thread中的一些方法的详解,一定要关注奥!

分享到:
评论

相关推荐

    JAVA多线程编程详解-详细操作例子

    本压缩包,总共包含两个文档,JAVA多线程编程详解-详细操作例子和 Java... 例如,runnable、thread、stop()、 suspend、yield、setPriority()、getPriority()、synchronized、wait()、join、线程池同步阻塞等方法的介绍

    java多线程机制 -- 源码详解

    在上述例子2中,我们在小程序这个主线程中用构造方法Thread(this)创建了一个新的线程。This代表着小程序作为这个新的线程的目标对象,因此我们的小程序必须为这个新创建的线程实现Runnable接口,即小程序利用...

    php多进程框架-模拟java多线程接口simple-fork-php.zip

    shutdown所有进程或单独stop一个进程时,可以注册覆盖beforeExit()方法,返回true则退出,false继续运行(在某些场景,进程不能立即退出) 支持子进程运行时reload 注意事项 ...

    JAVA并发编程实践-线程的关闭与取消-学习笔记

    java中没有提供任何机制,来安全是强迫线程停止手头的工作,Thread.stop和 Thread.suspend方法存在严重的缺陷,不能使用。程序不应该立即停止,应该采用中断这种协作机制来处理,正确的做法是:先清除当前进程中的...

    java多线程Thread的实现方法代码详解

    主要介绍了java多线程Thread的实现方法代码详解,涉及start(),run(),stop(),interrupt(),isInterrupted(),join()和join(long millis)等方法的介绍,具有一定借鉴价值,需要的朋友可以了解下。

    Java-并发-Java线程中断与停止线程详解

      Java 中的线程中断是一种线程间的协作模式,通过设置线程的中断标志并不能直接终止该线程的执行,而是被中断的线程根据中断状态自行处理。即“线程中断”并不是字面意思——线程真的中断了,而是设置了中断标志...

    java面试题(线程和JSP及EJB部分).pdf

    1、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 答:有两种实现方法,分别是继承Thread类与实现Runnable 接口 用synchronized 关键字修饰同步方法 反对...

    Java中interrupt的使用.docx

    在java的api中有stop、suspend等方法可以达到目的,但由于这些方法在使用上存在不安全性,会带来不好的副作用,不建议被使用。具体原因可以参考Why is Thread.stop deprecated。 在本文中,将讨论中断在java中的...

    java7源码-thread:多线程相关的学习

    Java多线程 [TOC] 线程状态 1.New:尚未启动的线程的线程状态 2.Runnable:可运行线程的线程状态,等待CPU调度 3.Blocked:线程阻塞等待监视器锁定的线程状态 4.Waiting:等待线程的线程状态(wait、join、park) 5....

    java笔试题大集合及答案(另附各大公司笔试题)

    60、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 答:有两种实现方法,分别是继承Thread类与实现Runnable接口 用synchronized关键字修饰同步方法 反对使用...

    Java中断线程的方法

    Thread.stop, Thread.suspend, Thread.resume 和Runtime.runFinalizersOnExit 这些终止线程运行的方法已经被废弃,使用它们是极端不安全的!  现在,如果你要安全有效地终止一个线程,应该采用以下这些方法: ...

    Java 多线程技术:(四)获取线程基本信息_暂停线程_线程的优先级_多线程的安全性_线程同步

    暂停线程执行 sleep_yield_join_stop3.线程的优先级问题4.多线程的安全性问题5.线程同步1.同步代码块2.同步方法 1.线程操作的常用方法 序号 方法名称 描述 1 static Thread currentThread() 返回目前正在执行...

    Java期末复习||应用程序设计-多线程和泛型

    Java应用程序设计之多线程和泛型 Thread、Runnable、Callable 线程操作:isAlive()、isInterrupted()、join()、sleep()、stop()、interrupted()、setDaemon()、setPriority()、yield() 同步与死锁、Object类对线程的...

    java课程设计报告-五子棋.doc

    创建线程的方法: 一种是创建Thread类的子类。另一种是实现Runnable接口.而本系统采用的是接口的方式 。 6.Applet小应用程序 、 小应用程序与应用程序的区别: 小应用程序没有主方法不能单独运行。而应用程序是拥有...

    实验多线程

    (1) 掌握线程与多线程的基本概念。 (2) 掌握创建线程的两种基本方法。...(3) 掌握Thread类得常用方法,如start(),run(),stop(),sleep()等的使用。 (4) 掌握编写同步代码的方法。

    java解惑--异常地危险

    在JDK1.2中,Thread.stop、Thread.suspend以及其他许多线程相关的方法都因为它们不安全而不推荐使用了。下面的方法展示了你用Thread.stop可以实现的可怕事情之一

    JAVA面试题最全集

    stop()和suspend()方法为何不推荐使用? 59.使用socket建立客户端与服务器的通信的过程 60.JAVA语言国际化应用,Locale类,Unicode 61.描述反射机制的作用 62.如何读写一个文件? 63.在图形界面中,一个按钮...

    java课程设计报告-五子棋(1).doc

    创建线程的方法: 一种是创建Thread类的子类。另一种是实现Runnable接口.而本系统采用的是接口的方式 。 6.Applet小应用程序 、 小应用程序与应用程序的区别: 小应用程序没有主方法不能单独运行。而应用程序是拥有...

    java课程设计报告-五子棋(2).doc

    创建线程的方法: 一种是创建Thread类的子类。另一种是实现Runnable接口.而本系统采用的是接口的方式 。 6.Applet小应用程序 、 小应用程序与应用程序的区别: 小应用程序没有主方法不能单独运行。而应用程序是拥有...

    java 面试题 总结

    sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。 wait是Object类的方法,对此对象调用wait方法导致本线程...

Global site tag (gtag.js) - Google Analytics