Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否存在使用当前线程的ExecutorService?_Java_Concurrency - Fatal编程技术网

Java 是否存在使用当前线程的ExecutorService?

Java 是否存在使用当前线程的ExecutorService?,java,concurrency,Java,Concurrency,我想要的是一种配置线程池使用与否的兼容方式。理想情况下,代码的其余部分根本不应该受到影响。我可以使用1个线程的线程池,但这不是我想要的。有什么想法吗 ExecutorService es = threads == 0 ? new CurrentThreadExecutor() : Executors.newThreadPoolExecutor(threads); // es.execute / es.submit / new ExecutorCompletionService(es) etc

我想要的是一种配置线程池使用与否的兼容方式。理想情况下,代码的其余部分根本不应该受到影响。我可以使用1个线程的线程池,但这不是我想要的。有什么想法吗

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.Yaitskov
terminated
字段将不会从基于此处实际代码的同步访问中受益。在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);
        }
    };
}