CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  Java >  J2SE / 基础类

如何从外界强制停止Thread类并释放它的资源?

楼主bbdolly(自己)2003-02-04 03:26:55 在 Java / J2SE / 基础类 提问

我实现了一个Thread的子类并且并且使其start,  
  我定时检查这个这个Thread中的一些我自己定义的一些状态,如果满足一定情况我希望可以从外界中断它并且释放他的资源。  
  但是stop()方法被标为   Deprecated,我如果直接把这个Thread对象置为null不知道可不可以强制停止这个正在运行的线程并释放资源。  
   
  我查看了一些资料,stop()方法被标为   Deprecated的原因是会是该线程锁住的资源得不到释放,而给出的替代办法是在run()里面的循环条件上加一个标志,从外部把这个标记置为false而使循环不再进行下去。  
  但在我的这个情况下我无法这样做,因为在我的这个线程的run()函数中调用的一些子函数好像会导致死循环,而我又无法去改写已经封装好的子函数…… 问题点数:20、回复次数:18Top

1 楼helpall(was jl)回复于 2003-02-04 06:00:36 得分 10

What   is   the   skeleton   of   your   run()?  
  like:  
      public   void   run()   {  
          ...  
          extern_func1(...);  
          ...  
      }  
   
  or:  
      public   void   run()   {  
          while(true)   {  
              ...  
              extern_func1(...);  
              ...  
          }  
      }  
  Top

2 楼simonjava()回复于 2003-02-04 07:29:19 得分 0

gzTop

3 楼bbdolly(自己)回复于 2003-02-04 10:29:22 得分 0

是这种样子的,没有循环的:  
   
      public   void   run()   {  
          ...  
          extern_func1(...);  
          ...  
      }  
   
  extern_func1(...);是一个别人写的关于ftp类的函数,实际使用中发现这个ftp类在连接有问题的ftp服务器时会出现停在某处不再反应的问题,于是我希望从外面强行中断它Top

4 楼jigsaw(echo)回复于 2003-02-04 22:19:03 得分 10

设置一个private   volatile(可能写错了?)   boolean   cancel   =   false;  
   
  run(){  
  while(!cancel){  
  //do   anything   u   want  
  }  
  }  
   
  然后public   void   cancel(){  
  cancel   =   true;  
  }  
   
  要废掉这个thread,调用cancel就行Top

5 楼helpall(was jl)回复于 2003-02-04 22:56:00 得分 0

I   really   don't   know   how   to   stop   the   thread   except   the   stop(but   stop()   does   not   release   the   resources   and   unsafe).    
   
  I   don't   think   jigsaw's   idea   will   work   because   the   program   has   no   chance   to   check   the   while(!cancel)   when   it's   executing   or   stuck   in   the   "//do   anything   u   wnat".Top

6 楼dd777(grass)回复于 2003-02-05 00:06:36 得分 0

我想对jigsaw(jigsaw)的方法作点补充,  
   
  再做一个线程,作为系统的主线程,监控包括你说的要运行的ftp线程,当满足一定条件时,更改while(!cancel)中的cancel,可以退出线程,这也是sun推荐的方法。  
   
  详细请:http://java.sun.com/products/jdk/1.2/docs/guide/misc/threadPrimitiveDeprecation.html  
  其中倒数第3问,比较适合。  
  Top

7 楼jigsaw(echo)回复于 2003-02-05 00:45:09 得分 0

helpall()    
   
  你确定我的方法不可以?你尝试一下把  
   
  注意   cancel被声明为volatileTop

8 楼jigsaw(echo)回复于 2003-02-05 00:49:20 得分 0

另外,如果把这个县城宣布为null很容易导致deadlockTop

9 楼bbdolly(自己)回复于 2003-02-05 01:50:17 得分 0

jigsaw(jigsaw):    
  问题正如helpall()说的那样,程序会在run()中一个函数上停住,而不会再运行到while(!cancel)处。  
   
  另外:volatile是什么啊?麻烦解释一下。  
  Top

10 楼helpall(was jl)回复于 2003-02-05 08:33:48 得分 0

to   jigsaw(jigsaw):    
  Here's   a   little   test   program   to   facilitate   your   testing.   If   you   really   can   work   it   out,   I   will   create   a   new   posting   to   score   you   200   points.   I   am   serious.  
  class   ThreadTest   extends   Thread   {  
                  public   volatile   boolean     isCancel   =   false;  
   
                  public   static   void   main(String[]   args)   {  
                                  ThreadTest   t   =   new   ThreadTest();  
                                  t.start();  
                                  wait(10);  
                                  t.isCancel   =   true;  
                                  System.out.println("\nMain   ends.");  
                                  wait(10);  
                  }  
   
                  public   void   run()   {  
                                  while(!isCancel)   {  
                                                  System.out.println("Enter   endless   loop");  
                                                  for(int   i   =   0;i   <   300   ;   i++)   {  
                                                                  wait(1);  
                                                                  System.out.print(i+"   ");  
                                                  }  
                                  }  
                                  System.out.println("End   endless   loop");  
                  }  
   
                  public   static   void   wait(int   second)   {  
                                  try{  
                                                  Thread.sleep(second   *   1000);  
                                  }catch(Exception   e){}  
                  }  
  }Top

11 楼jigsaw(echo)回复于 2003-02-05 13:24:21 得分 0

to   helpall:  
   
  I'm   sorry   I   was   totally   wrong.  
  However,   I've   figured   out   how   to   abort   or   cancel   a   living   thread.  
  Hope   this   time   I   didnt   make   any   mistakes.  
  Any   suggestion   will   be   highly   appreciated.  
   
  /*******************Poster   starts   here****************************/  
  public   class   Poster   implements   Runnable   {  
   
          private   String   query   =   null;  
          private   volatile   boolean   aborting   =   false;  
          private   boolean   isCanceled   =   false;  
   
          Poster()   {  
                  Thread   t   =   new   Thread(this);  
                  t.start();  
          }  
   
          public   synchronized   void   sendPost(String   query)   {  
                  this.query   =   query;  
                  notify();  
          }  
   
          public   void   run()   {  
                  running:  
                  while   (!aborting)   {  
                          String   query;  
                          synchronized   (this)   {  
                                  System.out.println("I'm   still   eligible   to   doSend");  
                                  while   (this.query   ==   null)   {  
                                          try   {  
                                                  wait();  
                                          }   catch   (InterruptedException   e)   {  
                                          }  
                                          if   (aborting)   {  
                                                  System.out.println("being   aborted");  
                                                  break   running;  
                                          }  
                                  }  
                                  query   =   this.query;  
                                  this.query   =   null;  
                          }  
                          //must   have   been   notified   by   sendPost  
                          doSend(query);  
                  }  
                  System.out.println("I'm   useless");  
          }  
   
          /*  
          *surppose   we   need   do   send   step   by   step,   either   step   is    
          *time   consuming  
          *the   1st   step   will   costs   3   sec(without   being   canceled),    
          *and   the   2nd   step  
          *will   never   end   untill   being   canceled.  
          */  
          private   void   doSend(String   query)   {  
                  int   i   =   0;  
                  for   (;   !isCanceled   &&   i   <   3;   i++)   {  
                          System.out.println(query   +   "   stepI   "   +   i);  
                          try   {  
                                  Thread.sleep(1   *   1000);  
                          }   catch   (InterruptedException   e)   {  
                          }  
                  }  
                  for   (;   !isCanceled;   i++)   {  
                          System.out.println(query   +   "   stepII   "   +   i);  
                          try   {  
                                  Thread.sleep(1   *   1000);  
                          }   catch   (InterruptedException   e)   {  
                          }  
                  }  
          }  
   
        /*  
        *This   is   just   for   tidying   up   -   the   instance   is   useless    
        *after   it   has  
        *been   called  
        */  
          public   void   abort()   {  
                  aborting   =   true;  
                  synchronized   (this)   {  
                          notify();   //   wake   up   our   posting   thread   and   kill   it  
                  }  
          }  
   
          public   synchronized   void   cancel()   {  
                  System.out.println("I'm   being   canceled,   however,   I'll   be   back   soon");  
                  isCanceled   =   true;  
          }  
   
          public   synchronized   void   resume()   {  
                  System.out.println("I'm   back   as   I've   told   you");  
                  isCanceled   =   false;  
          }  
  }  
  /**********************Poster   ends   here*****************/  
   
  /****************ThreadTest   starts   here**********/  
  public   class   ThreadTest   {  
          private   static   Poster   poster   =   new   Poster();  
   
          public   static   void   main(String[]   args)   {  
                  poster.sendPost("test");  
                  wait(2);  
                  poster.cancel();  
                  wait(5);  
                  poster.resume();//although   having   been   cancled,   the   thread   is   not   "dead"  
                  poster.sendPost("test2");  
                  wait(5);  
                  poster.cancel();//the   point   is:   before   aborting,   u   must   cancel   it   first  
                  poster.abort();//now   the   thread   is   useless  
                  poster.sendPost("test3");   //this   will   never   work  
          }  
   
          public   static   void   wait(int   second)   {  
                  try   {  
                          Thread.sleep(second   *   1000);  
                  }   catch   (InterruptedException   e)   {  
                  }  
          }  
  }  
   
  /****************ThreadTest   ends   here**********/  
  /**********************************************/  
   
  thank   you   for   your   testing  
   
  Best   Regards,  
  jigsawTop

12 楼helpall(was jl)回复于 2003-02-05 14:10:16 得分 0

to   jigsaw:  
        这一段程序应该没有问题,但还是没有能解决顶楼的问题啊。   你把isCanceled放到doSend中,而bbdolly没有你这么幸运啊。看来我还不能给你分,顶楼看着办吧。   :-)  
   
  Top

13 楼helpall(was jl)回复于 2003-02-05 14:12:00 得分 0

我觉得顶楼的问题没有什么好的方法解决。Top

14 楼jigsaw(echo)回复于 2003-02-05 14:16:25 得分 0

what's   more:  
   
  If   the   core   method   doSend()   doesnt   check   isCancled   on   each   step,   there's   no   way   out,   since   I   cant   find   any   solution   to   break   from   a   endless   loop   without   watching   on   a   certain   flag.  
  Only   on   condition   that   doSend()   will   never   end,   do   we   have   to   call   cancel()   before   abort().   Otherwise,   if   we   can   assure   that   doSend()   is   able   to   finish   its   work   and   give   us   a   response,   we   have   a   choice   to   wait   till   it   ends   and   then   abort   it.   Thus,   it's   optional   with   us   to   call   cancel()   or   not.  
   
  to   bbdolly:  
   
  Only   variables   may   be   volatile   ;   declaring   them   so   indicates  
  that   such   variables   might   be   modified   asynchronously,   so   the   compiler   takes   special   precautions.     --copied   from   sybex  
  Top

15 楼Norwaywoods()回复于 2003-02-05 15:41:15 得分 0

可以用interrupted()方法代替stop()呀!Top

16 楼Norwaywoods()回复于 2003-02-05 16:19:06 得分 0

看了前面的讨论,我觉得可以结合的来使用。  
  首先,肯定要有一个监视线程。如果,搂主连这个要求都无法满足,那就没戏了。  
  其次,设置一个volatile的flag。  
  再次,监视线程要保留该工作线程的一个reference(否则怎么监呀?)。  
   
  具体的机制:  
  当监视线程觉得可以干掉这个工作线程的时候,造一个InterruptException,终止正在运行的工作线程,这样就可以避免以下的情况:  
  (以下是引用前面的话)  
  jigsaw(jigsaw):    
  问题正如helpall()说的那样,程序会在run()中一个函数上停住,而不会再运行到while(!cancel)处。  
   
  这样不管是什么操作extern_func1(...)(这是搂主用来封装ftp函数的method),都会被迫终止。而去检查   stopRequested   这个flag了。然后,上面的兄弟都说了,我就不重复了。下面是我的例子:  
   
   
   
   
   
   
  public   class   KillMeSoftly   extends   Object   implements   Runnable   {  
   
                private   volatile   boolean   stopRequested;  
   
              private   Thread   runThread;  
   
   
   
              public   void   run()   {  
   
                    runThread   =   Thread.currentThread();  
   
                      stopRequested   =   false;  
   
   
   
                      int   count   =   0;  
   
   
   
                      while   (   !stopRequested   )   {  
   
                            System.out.println("Running   ...   count="   +   count);  
   
                              count++;  
   
   
   
                            try   {  
   
                                      Thread.sleep(300);  
   
                                }   catch   (   InterruptedException   x   )   {  
   
                                    System.out.println("Caught   a   InteruptedException!   It   is   time   to   check   the   stopRequested!");  
                                    Thread.currentThread().interrupt();   //   reassert  
   
                              }  
   
                      }  
   
              }  
   
   
   
              public   void   stopRequest()   {  
   
                      stopRequested   =   true;  
   
   
   
                      if   (   runThread   !=   null   )   {  
   
                                runThread.interrupt();  
   
                    }  
   
              }  
   
   
   
              public   static   void   main(String[]   args)   {  
   
                      AlternateStop   as   =   new   AlternateStop();  
   
                        Thread   t   =   new   Thread(as);  
   
                        t.start();  
   
   
   
                      try   {  
   
                            Thread.sleep(2000);  
   
                      }   catch   (   InterruptedException   x   )   {  
   
                              //   ignore  
   
                        }  
   
   
                      as.stopRequest();  
   
                }  
   
        }  
   
  在此郑重声明:此例子引用自  
  《Java   Thread   Programming》      
  Paul   Hyde    
  Copyright   &copy;   1999   Sams   Publishing    
  吐血推荐的好书呀!  
   
  如果搂主的ftp函数牵涉到I/O操作,那么上面的方法还是不行的。你就再开一个贴子问我吧!    
   
  Top

17 楼bbdolly(自己)回复于 2003-02-05 19:17:51 得分 0

谢谢大家如此热心的帮助!   :)  
   
  看来……基本上……这个问题……暂时是没有办法解决的。  
   
  不知道这种从外界停止一个线程是否在原理上就存在不可避免的安全隐患,还是sun公司发现从前写的stop()有问题但bug太深短时间无力补救只能很遗憾的建议大家从线程内部配合实现这个功能。  
   
  我是在做一个扫描ftp服务器上文件的程序遇到这个问题的。用的是NetComponents   中的com.oroinc.net.ftp这个类,这个东西在connect()某些有问题的ftp服务器时会死在这个函数,于是我做了个监视线程,发现这个线程一段时间没有动作后就kill掉它……  
   
  用interrupt(),然后置null不知道会不会有什么资源得不到释放的问题,由于这个程序基本上是不停的反复扫描,如果存在资源不能完全释放,会有一些隐患。  
   
  Top

18 楼jigsaw(echo)回复于 2003-02-05 19:35:19 得分 0

Norwaywoods可以共享一下那本书吗?  
   
  谢谢!Top

相关问题

  • 如何释放实例化后的类?
  • 如何释放实现了某接口的类实例!按如下情况释放为何会出错
  • 请教,类的释放:DESTROY、FREE、RELEASE有何区别?
  • 关于释放与创建类的问题!!
  • 关于类创建和释放的问题
  • 怎样释放类对象占用的内存? 散分!散分!
  • 基类中的指针由谁释放比较合适?
  • 基类中的指针由谁释放比较合适?
  • 关于类数组指针释放如问题:
  • 集合类释放问题!急,在线等,100分相送!!!!

关键词

  • 线程
  • 函数
  • 循环
  • jigsaw
  • cancel
  • 释放
  • iscancel
  • 资源
  • 类
  • threadtest

得分解答快速导航

  • 帖主:bbdolly
  • helpall
  • jigsaw

相关链接

  • CSDN Java频道
  • Java类图书
  • Java类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo