情景:多线程中个别线程执行时间会很长,如果线程执行时间超过某段时间,自动结束该线程
百度了很多答案之后大部分的解决办法都是利用Future类中的get(long timeout,TimeUnit unit) 方法进行设置,但是这个方法是阻塞的,在取不到结果之前是不会执行后边的程序的。
下面代码是按照这个方法进行的测试:
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(40);//创建一个可容纳40个线程的线程池
for(int i=0;i<40;i++){
System.out.println(i+"开始时间:"+System.currentTimeMillis());
Future future = pool.submit(new Runnable(){
@Override
public void run() {
try {
Thread.currentThread().sleep(300);
} catch (InterruptedException e) {
}
System.out.println("结束时间:"+System.currentTimeMillis());
}
});
try {
future.get(200, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
future.cancel(true);
} catch (ExecutionException e) {
future.cancel(true);
} catch (TimeoutException e) {
future.cancel(true);
}
}
}
预期结果:0到40都开始执行了之后,然后对线程进行超时判断
执行结果:0开始时间:1487675573448
结束时间:1487675573651
1开始时间:1487675573651
2开始时间:1487675573851
结束时间:1487675573851
3开始时间:1487675574052
结束时间:1487675574052
4开始时间:1487675574253
结束时间:1487675574253
。。。
会发现只有0结束后1才会开始,跟预期的结果不一致,完全没有起到多线程该有的作用!
解决方案:
究其根源其实是在get方法,get方法会一直等待线程完成后才会继续,解决思路就是:
让40个线程开始执行,然后再开40个线程分别进行get。
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(40);//创建一个可容纳40个线程的线程池
final List<Future> threadList = new ArrayList<Future>();
for(int i=0;i<40;i++){
System.out.println(i+"开始时间:"+System.currentTimeMillis());
Future future = pool.submit(new Runnable(){
@Override
public void run() {
try {
Thread.currentThread().sleep(300);
} catch (InterruptedException e) {
}
System.out.println("结束时间:"+System.currentTimeMillis());
}
});
threadList.add(future);
}
for(Future future:threadList){
final Future futureTemp = future;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
futureTemp.get(200, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
futureTemp.cancel(true);
} catch (ExecutionException e) {
futureTemp.cancel(true);
} catch (TimeoutException e) {
futureTemp.cancel(true);
}
}
});
t.start();
}
}
结果:
0开始时间:1487676230783
1开始时间:1487676230784
2开始时间:1487676230785
3开始时间:1487676230785
4开始时间:1487676230785
5开始时间:1487676230785
6开始时间:1487676230785
。。。
结束时间:1487676230993
结束时间:1487676230993
结束时间:1487676230993
结束时间:1487676230994
结束时间:1487676230994
结束时间:1487676230994
结束时间:1487676230994
。。。
完美解决。
总结:还是觉得jdk应该提供一个方法有个超时时间的参数,超过时间后线程自动结束。