J'ai un projet, disons projectA
qui avait un composant HTTP qui exposait sa logique aux clients.Le pilote Mongodb avec la bibliothèque mongodb bson provoque l'exécution de completableFuture lorsqu'il est utilisé dans des projets distincts
Dans ce projet, il y a un code comme tel:
void syncMethod() {
CompletableFuture<Void> f = new CompletableFuture<>();
someAsyncOperationThatReceivesACallback((Void x, Exception ex) -> {
if(ex != null) f.completeExceptionally(ex);
else f.complete(null); // An example of a result.
});
f.get(); // Wait unconditionally
}
Ce code fonctionne, comme il attend la fin de l'opération et l'avenir est complétée par le résultat de l'opération async.
Le besoin se faisait sentir de partager la logique entre 2 webapps et donc je me suis séparé projectA
dans 2 projets, disons projectA-LOGIC
et projectA-HTTP
où projectA-HTTP.dependsOn(projectA-LOGIC)
Avoir le point d'entrée dans projectA-HTTP
et le code ci-dessus dans le JAR emballé de projectA-LOGIC
le code ci-dessus a cessé de se terminer, ce qui signifie que le futur n'est jamais terminé et l'application se trouve juste là.
Si toutefois je crée un point d'entrée dans projectA-LOGIC
et exécutez le code ci-dessus tout fonctionne.
Je ne comprends pas la magie qui se passe ici. Actuellement en utilisant jdk8_111
. L'opération asynchrone décrite ci-dessus provient du mongodb async driver et est listCollectionNames. Toutes les opérations asynchrones (via callback) que j'essaye de faire synchroniser en utilisant des futurs subissent le même comportement quand j'ai 2 projets.
EDIT:
décharge du fil:
vidage filet plein
"[email protected]" prio=5 tid=0x1 nid=NA waiting
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Unsafe.java:-1)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.CompletableFuture$Signaller.block(CompletableFuture.java:1693)
at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3323)
at java.util.concurrent.CompletableFuture.waitingGet(CompletableFuture.java:1729)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
"cluster-ClusterId{value='588bc56a32de912224244114', description='null'}-127.0.0.1:[email protected]" daemon prio=5 tid=0xf nid=NA waiting
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Unsafe.java:-1)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.waitForSignalOrTimeout(DefaultServerMonitor.java:238)
at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.waitForNext(DefaultServerMonitor.java:219)
at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:168)
- locked <0x10fe> (a com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable)
at java.lang.Thread.run(Thread.java:745)
"[email protected]" daemon prio=5 tid=0x15 nid=NA waiting
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Unsafe.java:-1)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedNanos(AbstractQueuedSynchronizer.java:1037)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1328)
at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:277)
at com.mongodb.connection.BaseCluster$WaitQueueHandler.run(BaseCluster.java:464)
at java.lang.Thread.run(Thread.java:745)
"[email protected]" daemon prio=5 tid=0x14 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.Iocp.getQueuedCompletionStatus(Iocp.java:-1)
at sun.nio.ch.Iocp.access$300(Iocp.java:46)
at sun.nio.ch.Iocp$EventHandlerTask.run(Iocp.java:333)
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
"[email protected]" daemon prio=5 tid=0x13 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.Iocp.getQueuedCompletionStatus(Iocp.java:-1)
at sun.nio.ch.Iocp.access$300(Iocp.java:46)
at sun.nio.ch.Iocp$EventHandlerTask.run(Iocp.java:333)
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
"[email protected]" daemon prio=5 tid=0x12 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.Iocp.getQueuedCompletionStatus(Iocp.java:-1)
at sun.nio.ch.Iocp.access$300(Iocp.java:46)
at sun.nio.ch.Iocp$EventHandlerTask.run(Iocp.java:333)
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
"[email protected]" daemon prio=5 tid=0x11 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.Iocp.getQueuedCompletionStatus(Iocp.java:-1)
at sun.nio.ch.Iocp.access$300(Iocp.java:46)
at sun.nio.ch.Iocp$EventHandlerTask.run(Iocp.java:333)
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
"[email protected]" daemon prio=5 tid=0x10 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.Iocp.getQueuedCompletionStatus(Iocp.java:-1)
at sun.nio.ch.Iocp.access$300(Iocp.java:46)
at sun.nio.ch.Iocp$EventHandlerTask.run(Iocp.java:333)
at java.lang.Thread.run(Thread.java:745)
"[email protected]" daemon prio=8 tid=0x3 nid=NA waiting
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Object.java:-1)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
"Reference [email protected]" daemon prio=10 tid=0x2 nid=NA waiting
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Object.java:-1)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"Attach [email protected]" daemon prio=5 tid=0x5 nid=NA runnable
java.lang.Thread.State: RUNNABLE
"Signal [email protected]" daemon prio=9 tid=0x4 nid=NA runnable
java.lang.Thread.State: RUNNABLE
Ce que je ne comprends pas comment cela peut-il arriver juste en spliting le code dans des projets distincts. Pensez que je manque un détail subtil sur CompletableFutures ...
Je ne peux pas vraiment dire ce que cela pourrait être, mais je chercherais une impasse. Vérifiez également si rien d'autre n'utilise les threads du pool de threads commun. IIRC CompletableFuture utilise des threads du pool commun - peut-être essayer d'utiliser un pool séparé. – john16384
Voilà ce que je pense à, Ajout de vidage de thread. Mais j'aimerais comprendre ce qui se passe. – pedromss
Si c'est le vidage de thread, alors je ne pense pas que votre code soit en cours d'exécution, ce sont deux threads JVM uniquement. – john16384