经过好朋友的提示发现以上代码存在致命bug。
第一个线程调用 Sleep的时候,又调用Future的 cancel方法,其实cancel方法里调用的就是interrupt方法。第一个线程是在被挂起了,所以停止了。如使用了sleep,同步锁的wait,socket的receiver,accept等方法时,会使线程处于阻塞状态。当调用线程的interrupt()方法时,系统会抛出一个InterruptedException异常,代码中通过捕获异常,然后break跳出循环状态,使线程正常结束。
如果第一个线程执行复杂的运行,或者在执行对文件的读写操作的时候,就不行了。线程状态没有什么异常,是无论如何都不能停止的。除非这个线程执行完才行。
改造升级后的代码片段如下:
import java.math.BigInteger; import java.security.MessageDigest; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class TestClazz { private static Future future; public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(8); Callable task = new Callable () { @Override public String call() throws Exception { int i = 0; System.out.println("begin call"); String data = "123456abcdef"; while (i < 20) { i++; //Thread.currentThread().sleep(1000); data = hashtest(data); System.out.println(" call : " + i); System.out.println(" data : " + data); } return "ok"; } }; System.out.println("begin"); future = executor.submit(task); System.out.println("add ok"); Thread td = new Thread(new Runnable() { @Override public void run() { int j = 0; System.out.println("now start" + j); // System.out.println("now start" + (j > 15)); while (j < 15) { j++; System.out.println("thread: " + j); try { Thread.currentThread().sleep(800); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("now end"); future.cancel(true); } }); // td.interrupt() executor.submit(td); } private static String hashtest(String data){ for (int i = 0; i < 10000000; i++) { data = hash(data); } return data; } private static String hash(String inputStr) { BigInteger sha = null; // System.out.println("=======加密前的数据:" + inputStr); byte[] inputData = inputStr.getBytes(); try { MessageDigest messageDigest = MessageDigest.getInstance("SHA"); messageDigest.update(inputData); sha = new BigInteger(messageDigest.digest()); // System.out.println("SHA加密后:" + sha.toString(32)); } catch (Exception e) { e.printStackTrace(); } return sha.toString(32); } }还有一种费时的操作就是等待服务器响应了,类似于HTTP请求。这时候的线程处于挂起状态,还是可以通过interrupt来结束的,
类似的还有 同步锁的wait,socket的receiver,accept等方法
回过头来说,如果真的要结束第二个例子里的已启动的线程是无解的,对于如何结束一个正常状态的Thread,Java语言真的没有什么好的办法。算是一个bug吧。
还有其他结束线程的方式,这里不再冗述,大家可以查看其他相关技术资料。
