Java 是否存在使用当前线程的ExecutorService?
我想要的是一种配置线程池使用与否的兼容方式。理想情况下,代码的其余部分根本不应该受到影响。我可以使用1个线程的线程池,但这不是我想要的。有什么想法吗Java 是否存在使用当前线程的ExecutorService?,java,concurrency,Java,Concurrency,我想要的是一种配置线程池使用与否的兼容方式。理想情况下,代码的其余部分根本不应该受到影响。我可以使用1个线程的线程池,但这不是我想要的。有什么想法吗 ExecutorService es = threads == 0 ? new CurrentThreadExecutor() : Executors.newThreadPoolExecutor(threads); // es.execute / es.submit / new ExecutorCompletionService(es) etc
ExecutorService es = threads == 0 ? new CurrentThreadExecutor() : Executors.newThreadPoolExecutor(threads);
// es.execute / es.submit / new ExecutorCompletionService(es) etc
您可以使用RejectedExecutionHandler在当前线程中运行任务
public static final ThreadPoolExecutor CURRENT_THREAD_EXECUTOR = new ThreadPoolExecutor(0, 0, 0, TimeUnit.DAYS, new SynchronousQueue<Runnable>(), new RejectedExecutionHandler() {
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
r.run();
}
});
public static final ThreadPoolExecutor CURRENT\u THREAD\u EXECUTOR=new ThreadPoolExecutor(0,0,0,TimeUnit.DAYS,new SynchronousQueue(),new RejectedExecutionHandler()){
public void rejectedExecution(可运行的r、线程池执行器执行器){
r、 run();
}
});
您只需要其中的一个。这里有一个非常简单的
执行器
(注意,不是执行服务
)实现,它只使用当前线程。从“实践中的Java并发性”(基础阅读)中窃取了这一点
ExecutorService
是一个更复杂的接口,但可以用相同的方法处理。我基于AbstractExecutorService
编写了一个ExecutorService
/**
* Executes all submitted tasks directly in the same thread as the caller.
*/
public class SameThreadExecutorService extends AbstractExecutorService {
//volatile because can be viewed by other threads
private volatile boolean terminated;
@Override
public void shutdown() {
terminated = true;
}
@Override
public boolean isShutdown() {
return terminated;
}
@Override
public boolean isTerminated() {
return terminated;
}
@Override
public boolean awaitTermination(long theTimeout, TimeUnit theUnit) throws InterruptedException {
shutdown(); // TODO ok to call shutdown? what if the client never called shutdown???
return terminated;
}
@Override
public List<Runnable> shutdownNow() {
return Collections.emptyList();
}
@Override
public void execute(Runnable theCommand) {
theCommand.run();
}
}
/**
*直接在调用方所在的同一线程中执行所有提交的任务。
*/
公共类SameThreadExecutorService扩展了AbstractExecutorService{
//易失性,因为其他线程可以查看
私有易失布尔终止;
@凌驾
公共空间关闭(){
终止=真;
}
@凌驾
公共布尔值isShutdown(){
终止返回;
}
@凌驾
公共布尔值已取消(){
终止返回;
}
@凌驾
公共布尔等待终止(long theTimeout,TimeUnit theUnit)抛出中断异常{
shutdown();//是否要调用shutdown?如果客户端从未调用shutdown???
终止返回;
}
@凌驾
公开列表关闭现在(){
返回集合。emptyList();
}
@凌驾
public void execute(可运行命令){
命令run();
}
}
您可以使用番石榴,或者如果您不需要ExecutorService
/**
* Executes all submitted tasks directly in the same thread as the caller.
*/
public class SameThreadExecutorService extends AbstractExecutorService {
//volatile because can be viewed by other threads
private volatile boolean terminated;
@Override
public void shutdown() {
terminated = true;
}
@Override
public boolean isShutdown() {
return terminated;
}
@Override
public boolean isTerminated() {
return terminated;
}
@Override
public boolean awaitTermination(long theTimeout, TimeUnit theUnit) throws InterruptedException {
shutdown(); // TODO ok to call shutdown? what if the client never called shutdown???
return terminated;
}
@Override
public List<Runnable> shutdownNow() {
return Collections.emptyList();
}
@Override
public void execute(Runnable theCommand) {
theCommand.run();
}
}
如果包含番石榴太重,您可以实施一些几乎同样好的措施:
public final class SameThreadExecutorService extends ThreadPoolExecutor {
private final CountDownLatch signal = new CountDownLatch(1);
private SameThreadExecutorService() {
super(1, 1, 0, TimeUnit.DAYS, new SynchronousQueue<Runnable>(),
new ThreadPoolExecutor.CallerRunsPolicy());
}
@Override public void shutdown() {
super.shutdown();
signal.countDown();
}
public static ExecutorService getInstance() {
return SingletonHolder.instance;
}
private static class SingletonHolder {
static ExecutorService instance = createInstance();
}
private static ExecutorService createInstance() {
final SameThreadExecutorService instance
= new SameThreadExecutorService();
// The executor has one worker thread. Give it a Runnable that waits
// until the executor service is shut down.
// All other submitted tasks will use the RejectedExecutionHandler
// which runs tasks using the caller's thread.
instance.submit(new Runnable() {
@Override public void run() {
boolean interrupted = false;
try {
while (true) {
try {
instance.signal.await();
break;
} catch (InterruptedException e) {
interrupted = true;
}
}
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}});
return Executors.unconfigurableScheduledExecutorService(instance);
}
}
public final类SamethreadExecutor服务扩展ThreadPoolExecutor{
专用最终倒计时锁存器信号=新倒计时锁存器(1);
私有SameThreadExecutorService(){
super(1,1,0,TimeUnit.DAYS,新的SynchronousQueue(),
新的ThreadPoolExecutor.CallerRunPolicy());
}
@覆盖公共无效关闭(){
super.shutdown();
信号。倒计时();
}
公共静态执行器服务getInstance(){
返回SingletonHolder.instance;
}
私有静态类单音持有人{
静态ExecutorService实例=createInstance();
}
私有静态ExecutorService createInstance(){
最后一个SameThreadExecutorService实例
=新的SameThreadExecutorService();
//执行器有一个工作线程。请为其指定一个等待的可运行线程
//直到executor服务关闭。
//所有其他提交的任务将使用RejectedExecutionHandler
//它使用调用方的线程运行任务。
submit(新的Runnable(){
@重写公共无效运行(){
布尔值=假;
试一试{
while(true){
试一试{
instance.signal.await();
打破
}捕捉(中断异常e){
中断=真;
}
}
}最后{
如果(中断){
Thread.currentThread().interrupt();
}
}
}});
返回Executors.unconfigurableScheduledExecutorService(实例);
}
}
Java 8风格:
Executor e=Runnable::run代码>出于测试目的,我不得不使用相同的“CurrentThreadExecutorService”,尽管所有建议的解决方案都很好(特别是提到的那个),但我还是提出了一些类似于Peter Lawrey建议的解决方案
正如Axelle Ziegler所提到的,不幸的是,Peter的解决方案实际上不起作用,因为在ThreadPoolExecutor
中对maximumPoolSize
构造函数参数引入了检查(也就是说,maximumPoolSize
不可能是+1:正如你所说,ExecutorService可以用同样的方式处理,也许可以通过对AbstractExecutorService进行子类化。@Paul Yep,AbstractExecutorService
看起来是一个不错的选择。在Java8中,你可以将其简化为Runnable::run
@Juude,它将始终运行在lls是执行器。同一个线程执行器的目的不是能够从execute()中安排更多任务吗?这个答案不行。我找不到满足这个要求的答案。聪明!这有多安全(诚实的问题)?如果您实际上不想在当前线程中执行任务,是否有任何方法可以拒绝该任务?如果ExecutorService正在关闭或终止,任务是否会被拒绝?由于最大大小为0,因此每个任务都会被拒绝。但是,被拒绝的行为将在当前线程中运行。只有task未被拒绝。注意,此策略已经有了实现,无需定义自己的java.util.concurrent.ThreadPoolExecutor.CallerRunPolicy
。无法再创建最大池大小为0的ThreadPoolExecutor。我想可以使用大小为0的blockingQueue重现此行为,但是似乎没有默认实现允许这样做。由于{code}if,它将不会编译(corePoolSize<0 | | maximumPoolSize终止字段不受synchronized的保护。@DaneelS.Yaitskovterminated
字段将不会从基于此处实际代码的同步访问中受益。在Java中,对32位字段的操作是原子的。我假设isTerminated()上面的方法不太正确
private static ExecutorService currentThreadExecutorService() {
CallerRunsPolicy callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();
return new ThreadPoolExecutor(0, 1, 0L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), callerRunsPolicy) {
@Override
public void execute(Runnable command) {
callerRunsPolicy.rejectedExecution(command, this);
}
};
}