,,,线程的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);//中断应用程序 } }
,,,某次运行结果如下:
,,,从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并发编程之线程挂起,恢复与终止