Java并发编程之线程挂起,恢复与终止

  

  

,,,线程的API中包含两个被淘汰的方法,它们用于临时挂起和重启某个线程,这些方法已经被淘汰,因为它们是不安全的,不稳定的。如果在不合适的时候挂起线程(比如,锁定共享资源时),此时便可能会发生死锁条件,其他线程在等待该线程释放锁,但该线程却被挂起了,便会发生死锁。另外,在长时间计算期间挂起线程也可能导致问题。

  

,,,下面的代码演示了通过休眠来延缓运行,模拟长时间运行的情况,使线程更可能在不适当的时候被挂起:

        公开课DeprecatedSuspendResume扩展对象实现Runnable {//不稳定的关键字,表示该变量可能在被一个线程使用的同时,被另一个线程修改   私人int firstVal波动;   私人int secondVal波动;//判断二者是否相等   公共布尔areValuesEqual () {   返回(firstVal==secondVal);   }   公共空间run () {   尝试{   firstVal=0;   secondVal=0;   workMethod ();   }捕捉(InterruptedException x) {   system . out。println(“中断在workMethod () ");   }   }   私人空间workMethod()抛出InterruptedException {   int val=1;   而(真){   stepOne (val);   stepTwo (val);   val + +;   thread . sleep (200);//再次循环钱休眠200毫秒   }   }//赋值后,休眠300毫秒,从而使线程有机会在stepOne操作和stepTwo操作之间被挂起   私人空间stepOne (int newVal)抛出InterruptedException {   firstVal=newVal;   thread . sleep (300);//模拟长时间运行的情况   }   私人空间stepTwo (int newVal) {   secondVal=newVal;   }   公共静态void main (String [] args) {   DeprecatedSuspendResume域=new DeprecatedSuspendResume ();   线程t=新线程(域);   t.start ();//休眠1秒,让其他线程有机会获得执行   尝试{   thread . sleep (1000);}   抓住(InterruptedException x) {}   for (int i=0;我& lt;10;我+ +){//挂起线程   t.suspend ();   System.out.println (“dsr.areValuesEqual ()=" + dsr.areValuesEqual ());//恢复线程   t.resume ();   尝试{//线程随机休眠0 ~ 2秒   thread . sleep((长)(math . random () * 2000.0));   }捕捉(InterruptedException x) {//略   }   }   system . exit (0);//中断应用程序   }   }      

,,,某次运行结果如下:

  

 Java并发编程之线程挂起,恢复与终止

  

,,,从areValuesEqual()返回的值有时为真,有时为假的。以上代码中,在设置firstVal之后,但在设置secondVal之前,挂起新线程会产生麻烦,此时输出的结果会为假(情况1),这段时间不适宜挂起线程,但因为线程不能控制何时调用它的暂停方法,所以这种情况是不可避免的。

  

,,,当然,即使线程不被挂起(注释掉挂起和恢复线程的两行代码),如果在主要线程中执行asr.areValuesEqual()进行比较时,恰逢stepOne操作执行完,而stepTwo操作还没执行,那么得到的结果同样可能是假的(情况2)。

  

,,,,下面我们给出不用上述两个方法来实现线程挂起和恢复的策略,设置标志位。通过该方法实现线程的挂起和恢复有一个很好的地方,就是可以在线程的指定位置实现线程的挂起和恢复,而不用担心其不确定性只

  

,,,,对于上述代码的改进代码如下:

        公开课AlternateSuspendResume扩展对象实现Runnable {   私人int firstVal波动;   私人int secondVal波动;//增加标志位,用来实现线程的挂起和恢复   私人动荡的布尔暂停;   公共布尔areValuesEqual () {   返回(firstVal==secondVal);   }   公共空间run () {   尝试{   暂停=false;   firstVal=0;   secondVal=0;   workMethod ();   }捕捉(InterruptedException x) {   system . out。println(“中断在workMethod () ");   }   }   私人空间workMethod()抛出InterruptedException {   int val=1;   而(真){//仅当贤臣挂起时,才运行这行代码   waitWhileSuspended ();   stepOne (val);   stepTwo (val);   val + +;//仅当线程挂起时,才运行这行代码   waitWhileSuspended ();   thread . sleep (200);   }   }   私人空间stepOne (int newVal)   抛出InterruptedException {   firstVal=newVal;   thread . sleep (300);   }   私人空间stepTwo (int newVal) {   secondVal=newVal;   }   公共空间suspendRequest () {   暂停=true;   }   公共空间resumeRequest () {   暂停=false;   }   私人空间waitWhileSuspended ()   抛出InterruptedException {//这是一个“繁忙等待“技术的示例。//它是非等待条件改变的最佳途径,因为它会不断请求处理器周期地执行检查,//更佳的技术是:使用Java的内置“通知——等待“机制   而(暂停){   thread . sleep (200);   }   }   公共静态void main (String [] args) {   AlternateSuspendResume asr=新AlternateSuspendResume ();   线程t=新线程(asr);   t.start ();//休眠1秒,让其他线程有机会获得执行   尝试{thread . sleep (1000);}   抓住(InterruptedException x) {}   for (int i=0;我& lt;10;我+ +){   asr.suspendRequest ();//让线程有机会注意到挂起请求//注意:这里休眠时间一定要大于//stepOne操作对firstVal赋值后的休眠时间,即300毫秒,//目的是为了防止在执行asr.areValuesEqual()进行比较时,//恰逢stepOne操作执行完,而stepTwo操作还没执行   尝试{thread . sleep (350);}   抓住(InterruptedException x) {}   System.out.println (“dsr.areValuesEqual ()=" +   asr.areValuesEqual ());   asr.resumeRequest ();   尝试{//线程随机休眠0 ~ 2秒   thread . sleep (   (长)(math . random () * 2000.0));   }捕捉(InterruptedException x) {//略   }   }   system . exit (0);//退出应用程序   }   }

Java并发编程之线程挂起,恢复与终止