У меня есть проект, скажем projectA
, у которого был HTTP-компонент, который разоблачил его логику для клиентов.Драйвер Mongodb с библиотекой mongodb bson вызывает завершениеFuture зависает при использовании в отдельных проектах
В рамках этого проекта есть код, как например:
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
}
И этот код работает, как он ожидает завершения операции и будущее завершается с результатом асинхронной операции.
Возникла необходимость разделить логику между 2 WebApps и поэтому я отделенной projectA
в 2-х проектов, скажем projectA-LOGIC
и projectA-HTTP
где projectA-HTTP.dependsOn(projectA-LOGIC)
Имея точку входа в projectA-HTTP
и код выше в упакованном JAR из projectA-LOGIC
вышеописанный код завершен, что означает, что будущее никогда не завершается, и приложение просто стоит там.
Если, однако, я создаю точку входа в projectA-LOGIC
и запускаю код над всем, что работает.
Я не понимаю магию, которая здесь происходит. В настоящее время используется jdk8_111
. Асинхронная операция, абстрагированная выше, происходит от mongodb async driver и составляет listCollectionNames. Все операции async (через обратный вызов) я пытаюсь выполнить синхронизацию с использованием фьючерсов, которые имеют одинаковое поведение, когда у меня есть 2 проекта.
EDIT:
свалка Тема:
Полный поток свалка
"[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
То, что я не могу понять, как это может произойти только путем spliting кода в отдельные проекты. Подумайте, я пропустил некоторые тонкие подробности о CompletableFutures ...
Я не могу сказать, что это может быть, но я искал бы тупик. Также проверьте, не использует ли ничего из потоков из общего пула потоков. IIRC CompletedFuture использовать потоки из общего пула - может попробовать использовать отдельный пул. – john16384
Вот что я думаю, добавил дамп потока. Но я хотел бы понять, что происходит. – pedromss
Если это дамп потока, то я не думаю, что какой-либо из ваших кодов работает вообще, это только два потока JVM. – john16384