我正在利用ExcutorService
提交并行运行的任务。任务的顺序无关紧要。但是,服务可能会更改,特别是在请求的池大小需要更改时。
public class Service {
private volatile ExecutorService service = Executors.newFixedThreadPool(4);
private final ReentrantLock serviceLock = new ReentrantLock();
public Future<Object> postRequest(final Callable<Object> request) {
try {
serviceLock.lock(); // ?
return service.submit(request);
} finally {
serviceLock.unlock(); // ?
}
}
public void setSize(final int size) {
try {
if (size <= 0) {
throw new IllegalArgumentException("service pool size must positive");
}
serviceLock.lock();
service = Executors.newFixedThreadPool(size);
} finally {
serviceLock.unlock();
}
}
}
显然,当postRequest
方法被调用时,我认为我不需要锁定和解锁。
我只需要在访问postRequest
期间锁定setSize
。否则,锁定和解锁所需的额外时间毫无意义。我认为这是必要的,因为与提交的数百个请求相比,大小很少会改变(可能是一次或两次)。
有没有办法避免在postRequest
不需要时锁定(setSize
未被访问时)?
答案 0 :(得分:0)
由于Executor实际上是一个ThreadPoolExecutor,你可以应用一个强制转换并使用它的setMaximumPoolSize方法。
如果将来更新JVM规范,您可以在setSize方法中添加类型检查。
if (e instanceof ThreadPoolExecutor) {
((ThreadPoolExecutor) e).setMaximumPoolSize(size);
}
答案 1 :(得分:0)
@Obicere,你是对的,你不需要锁定会有性能开销的postRequest
。
在postRequest
public Future<Object> postRequest(final Callable<Object> request) {
try {
while(serviceLock.isLocked()) { // i.e acquired by setSize method
Thread.currentThread().sleep(/*some very small time */);
}
return service.submit(request);
} finally {
}
}
另外,请考虑使用ThreadPoolExecutor
而不是FixedPoolThread,因为在您的情况下,它从来不是固定的池线程:)
答案 2 :(得分:0)
您可以显式创建线程池执行程序,然后使用setMaximumPoolSize():
private final ThreadPoolExecutor service = new ThreadPoolExecutor(4,4,0, TimeUnit.MINUTE, new LinkedBlockingQueue());
public void setSize(final int size) {
service.setMaximumPoolSize(size);
}