Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Future's default ExecutorService a configurable non-singleton #1573

Closed
danieldietrich opened this issue Sep 18, 2016 · 5 comments
Closed

Comments

@danieldietrich
Copy link
Contributor

Currently we have

public interface Future<T> extends Value<T> {

    ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();

}

Configurable

Goal is to make the DEFAULT_EXECUTOR_SERVICE configurable.

public interface Future<T> extends Value<T> {

    ExecutorService DEFAULT_EXECUTOR_SERVICE = ExecutorServiceConfiguration.createDefaultExecutorServiceFactory();

}

Maybe we should also support loading additional configurations:

public final class ExecutorServiceConfiguration {

    private static final Map<String, ...> CONFIG;

    static {
        // load config...
        CONFIG = ...
    }

    private ExecutorServiceConfiguration() {
    }

    public static Supplier<ExecutorService> createDefaultExecutorServiceFactory() {
        return createExecutorServiceFactory("default");
    }

    public static Supplier<ExecutorService> createExecutorServiceFactory(String name) {
        return () -> createExecutorService(CONFIG.get(name).getOrElseThrow(cause -> ...));
    }
}

Non-singleton

Also the DEFAULT_EXECUTOR_SERVICE currently maybe shut down via shutdown() by client code. This can be considered as bug. We need a provider that provides Future instances with new default ExecutorService instances.

@danieldietrich danieldietrich added this to the 2.2.0 milestone Sep 18, 2016
@danieldietrich danieldietrich modified the milestones: 2.1.0, 2.2.0 Oct 23, 2016
@mvh77
Copy link
Contributor

mvh77 commented Jan 8, 2017

I think having a default executor has a few problems. One of them is that the executor will hang around until its threads are cleaned up, which seems to be around 1min with the jdk cached thread pool. This means if you run unit tests that use Futures your test will complete 1min after it's really finished, unless you explicitly shutdown the executor, and this even if you don't use the default executor and give your own on all operations. The default executor should be lazy.

I've personally been experimenting with the idea of an ExecutionContext that you create by giving it your Executor and you can only get futures and promises from that EC. This way there are no hidden executors hanging around and the user has full power over the threads the tasks are executed on.

@danieldietrich
Copy link
Contributor Author

@mvh77 thank you for the hint! I also think that this topic needs to be investigated, it is not trivial.

Maybe we could wrap the default executor and prevent it from shutdown. Internally we could add a JVM shutdown hook that shuts down the default executor when the JVM exits. Don't know if that works well.

Do you have a Gist with code examples of your experiments?

@mvh77
Copy link
Contributor

mvh77 commented Jan 9, 2017

Hi. I don't think a shutdown hook helps very much, at least in the case I mentioned as it would be executed only after the 1min. I have my version here (javadocs probably aren't up to date).

With an execution context it would also be possible to have a configurable policy on how to handle fatal vs. non-fatal exceptions (if there's no satisfactory solution to that problem yet).

@Ramblurr
Copy link

Ramblurr commented Jan 13, 2017

I have an application that is short lived. It is booted up, does some work, and then exits.

I'm using javaslang Future, and the defaule ExecutorService seems to be preventing the JVM from exiting cleanly. Is there any way to get a handle on the ExecutorService instance so I can call shutdown?

answering my own question: the DEFAULT_EXECUTOR_SERVICE is part of the public interface so you can grab it directly with Future.DEFAULT_EXECUTOR_SERVICE

@danieldietrich danieldietrich modified the milestones: 3.0.0, 2.1.0 Mar 5, 2017
@danieldietrich danieldietrich modified the milestones: vavr-0.9.0, vavr-1.0.0 Apr 21, 2017
@danieldietrich danieldietrich modified the milestones: vavr-1.0.0, vavr-0.9.0 May 7, 2017
@danieldietrich
Copy link
Contributor Author

@mvh77 is right, this is risky and introduces unexpected behavior.

I addressed @Ramblurr's wish in #2093. We are now using ForkJoinPool.commonPool(), like Scala. It creates daemon threads that do not prevent the VM from shutdown.

@danieldietrich danieldietrich removed this from the vavr-1.0.0 milestone Oct 23, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants