public void btnTestOnMouseClicked(MouseEvent event)
{
System.out.println("futuretask "+futureTask.isDone()+":"+futureTask.isCancelled());
}
FutureTask futureTask;
public void btnFUNOnMouseClicked(MouseEvent event)
{
futureTask.cancel(true);
}
public void btnSetIpMouseClicked(MouseEvent event)
{
futureTask = new FutureTask(new Callable() {
@Override
public Object call() throws Exception {
while(!Thread.currentThread().isInterrupted())
{
System.out.println("running...");
// Thread.sleep(1000);
for(int i=0;i<150000000;i++){}
}
System.out.println("quit");
return "exit ok";
}
});
new Thread(futureTask).start();
}
本代码执行启动futuretask之后,再cancel,然后再打印isDone和isCancel,实验结果如下:
running...
running...
running...
quit
futuretask true:true
如果将代码中的for(int i=0;i<150000000;i++){}注释,换成Thread.sleep(1000);则实验结果如下:
running...
running...
running...
futuretask true:true
发现只是少了quit这句显示。
这个现象的原理是:
java的FutureTask的Cancel方法并不是真的中止线程,java目前已经将stop(中止线程执行)函数抛弃了,所以Cancel只是调用了Thread的interrupt方法,而interrupt方法只是停掉有sleep,wait,join操作的线程的逻辑,并抛出interruptException,(本例可知肯定抛出了interruptException,但并没有造成进程异常,这是为什么呢???)而其它线程则只是将线程的标志位置了一个interrupt标志,所以上面没有sleep的代码能显示出来quit,而有sleep的代码因出现interruptException而异常中止退出了,当然不会显示quit,只不过通过这个实验即使cancel了,isDone也是true,那如果要取值会发现什么现象呢?应该不能取到值,毕竟被取消了,不可能有返回值,感觉会出异常:
System.out.println("futuretask"+futureTask.isDone()+":"+futureTask.isCancelled());
System.out.println("futuretask"+futureTask.isDone()+":"+futureTask.isCancelled());
if(futureTask.isDone()) {
try {
System.out.println(futureTask.get().toString());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
}
running...
running...
futuretasktrue:true
futuretasktrue:true
java.util.concurrent.CancellationException
。。。。。。
确实是出现了异常,是CancellationException.
后来还做了一点总结:
如果线程中sleep,futuretask执行了cancel方法,马上判断isCancelled则是true,如果线程中是for(....)循环,执行了cancel方法马上判断isCancelled则也是true,当然,这咱情况线程不是立刻退出,是执行完for循环之后再到while(!Thread.currentThread().isInterrupted())时才退了。FutureTask只能用一次,不管是正常执行完毕还是被cancel,下次再用必须要重新new。