11
回答
Java 还有什么更高效的“在规定时间内执行某个方法”的办法吗?

使用 ExecutorService 进行调度的话,调度本身耗时挺高,如下面代码:

任务本身没有任何延迟,这样的代码执行耗时 50 毫秒以上(Mac Pro 机器,i7处理器)

public class TaskExecutor {

    /**
     * 在指定毫秒内完成某个任务并返回结果
     * @param task
     * @param millSeconds
     * @return
     */
    public static Object execute(Callable<Object> task, int millSeconds) {
        Object result = null;
        ExecutorService threadPool = Executors.newFixedThreadPool(1);
        try {
            Future<Object> future = threadPool.submit(task);
            result = future.get(millSeconds, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | TimeoutException e) {
        } catch (ExecutionException e) {
            throw new RuntimeException(e.getCause());
        } finally  {
            threadPool.shutdownNow();
        }
        return result;
    }

    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        long ct = System.currentTimeMillis();
        System.out.println(execute(()->{
            //Thread.sleep(400);
            return "hello";
        }, 1000));
        System.out.printf("Execute time :%d ms\n", (System.currentTimeMillis() - ct));
    }

}

这 50 毫秒的耗时没法接受啊,还有什么其他方法更高效吗?

举报
红薯
发帖于6个月前 11回/987阅
共有11个答案 最后回答: 5个月前

首先,要实现任意任务的超时,只能用线程。比较高效的办法就是用线程池去重用它。

需要预先分配一定数量的工作线程(不要在execute里分配,同时也不要在execute里shutdown那些)。就像你的逻辑,每次把任务提交给线程池,然后用future实现超时。

这里有个细节,交给线程池实现的线程最好实现如下接口。

interface task extends Callable<Object> {
    public void terminate();
}

让execute函数在超时后调用terminate函数终止运行。具体terminate的实现可根据Callable的功能自定义处理。比如如果是计算密集的,那就写一个volatile标记,如果是网络通信的,直接close相关socket让它报错。

package org.tio.core.ssl;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class TaskExecutor2 {

	public TaskExecutor2() {
		// TODO Auto-generated constructor stub
	}
	static ExecutorService threadPool = Executors.newFixedThreadPool(1);
	 /**
     * 在指定毫秒内完成某个任务并返回结果
     * @param task
     * @param millSeconds
     * @return
     */
    public static Object execute(Callable<Object> task, int millSeconds) {
        Object result = null;
        
        try {
            Future<Object> future = threadPool.submit(task);
            result = future.get(millSeconds, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | TimeoutException e) {
        } catch (ExecutionException e) {
            throw new RuntimeException(e.getCause());
        } finally  {
            //threadPool.shutdownNow();
        }
        return result;
    }

    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        for(int i = 0; i <100; i++) {
        	test();
        }
    }
    
    public static void test() {
        long ct = System.currentTimeMillis();
        System.out.println(execute(()->{
            //Thread.sleep(400);
            return "hello";
        }, 1000));
        System.out.printf("Execute time :%d ms\n", (System.currentTimeMillis() - ct));
    }
}

 

 

这样写,除了第一次要50ms外,其它都是0秒

顶部