Giter Club home page Giter Club logo

Comments (3)

bgloeckle avatar bgloeckle commented on May 23, 2024

Just for a quick illustration of the problem: Basically this is what happens:

public class CompletableFutureTest {
  public static void main(String[] args) throws InterruptedException {
    Executor executor = Executors.newSingleThreadScheduledExecutor();

    System.out.println(Thread.currentThread().getId() + ": Main thread");

    CompletableFuture<Void> f = new CompletableFuture<>();

    executor.execute(() -> {
      try {
        f.whenComplete((r, e) -> {
          System.out.println(Thread.currentThread().getId() + ": Complete!");
        });
        Thread.sleep(1000);
        f.complete(null);
      } catch (Exception e) {
        e.printStackTrace();
      }
    });

    Thread.sleep(3000);
    f.thenCompose(v -> {
      System.out.println(Thread.currentThread().getId() + ": thenCompose!");
      return new CompletableFuture<>();
    });
  }
}

Output is:

1: Main thread
10: Complete!
1: thenCompose!

That means that the Function we pass in "thenCompose" is executed on the main thread, but copycat expects it to be executed on the same thread as the one writing "10: Complete!".

from copycat.

kuujo avatar kuujo commented on May 23, 2024

The Copycat client internals have been completely rewritten, but I think we still do need to do some review of that code before a full release to make sure this issue is not present. I've seen some non-intuitive behavior in CompletableFuture, particularly with thenCompose.

@bgloeckle correct me if I'm wrong, but essentially what you're seeing is if the main thread gets to the thenCompose call after the future being composed is completed, CompletableFuture will run the composed callback on the main thread rather than the thread that completed it?

A while back, we actually had similar issues with thenComposeAsync causing deadlocks in the server. I found an obscure reference to an issue in the CompletableFuture implementation that was fixed in some later Java releases, and I removed all use of thenComposeAsync.

I think I may just want to do the same thing and replace thenCompose calls with a helper for internal use that ensures composed callbacks are executed on the proper thread (the thread that completed the future). Its use only seems to be safe inside the Copycat server where futures are created and completed on the same thread. Most of the other code that completes futures on a thread other than the one on which it was created already account for this issue by explicitly completeing futures in a specific thread.

I will go through and check all the uses of this method. If this pattern isn't being used in the new client I'll close this.

from copycat.

bgloeckle avatar bgloeckle commented on May 23, 2024

@bgloeckle correct me if I'm wrong, but essentially what you're seeing is if the main thread gets to the thenCompose call after the future being composed is completed, CompletableFuture will run the composed callback on the main thread rather than the thread that completed it?

Yes, that's what I was seeing (I think that was on the "beta5" release). I did not yet check all the code again for the newer releases (I'm just in the process of switching diqube to copycat rc2), but essentially all the methods that create the "pipeline" that will be executed as soon as a CompletableFuture is completed should themselves take care of being executed on the correct thread. I think it's a good idea to have a single utility class for that in copycat.

from copycat.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.