假设您有一个OdbcCaller
:
public class OdbcCaller {
public void callODBC() {
// call ODBC directly
// ...
}
您可以将其包装在一个可运行的任务中并将该任务提交到线程池以使其异步执行:
public void asyncCallODBC() {
// wrap the call with a runnable task
executor.execute(new Runnable() {
@Override
public void run() {
callODBC();
}
});
// the above line would return immediately.
}
是JDK提供的executor
线程池实现,可以定义如下:
Executor executor = new ThreadPoolExecutor(/* core pool size */5,
/* maximum pool size */10,
/* keepAliveTime */1,
/* time unit of keepAliveTime */TimeUnit.MINUTES,
/* work queue */new ArrayBlockingQueue<Runnable>(10000),
/* custom thread factory */new ThreadFactory() {
private AtomicInteger counter = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "asyncCaller-" + (counter.incrementAndGet()));
return t;
}
},
/*
* policy applied when all tasks are occupied and task
* queue is full.
*/new ThreadPoolExecutor.CallerRunsPolicy());
它ThreadPoolExecutor
是高度可配置的,并且在JavaDoc中有很好的记录,您可能需要先阅读它。
以下是根据我的经验对线程池配置的一些建议:
- 正确的线程池大小取决于场景,您可能需要运行一些测试来调整它。
- 当没有可用的工作线程时,工作队列用于缓存任务。无界队列不是一个好主意,因为您可能会耗尽内存。
ThreadFactory
为线程提供一个有意义的名称是一种很好的做法。jstack
当您需要检查线程状态(使用或其他工具)时,它将非常有用。
- 当没有可用资源时应用拒绝策略。您可以选择一种内置策略(reject、discard、caller-run、discardOldest),或实施您自己的策略。