2015-04-14 39 views
15

Mam program Java, biorąc 100% procesora, ale pozornie nic nie robi.Nieskończona pętla w EventQueue.isDispatchThread()

Jeśli wykonam zrzut wątku, czekają na niego 4 wątki (z puli 5).

"Incoming WorkPool 5" - Thread [email protected] 
    java.lang.Thread.State: WAITING 
    at sun.misc.Unsafe.park(Native Method) 
    - waiting to lock <7212149b> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) owned by "Incoming WorkPool 3" [email protected] 
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:834) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:867) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197) 
    at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:214) 
    at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290) 
    at java.awt.EventQueue.isDispatchThreadImpl(EventQueue.java:1019) 
    at java.awt.EventQueue.isDispatchThread(EventQueue.java:1014) 

Gwint czekają na to Runnable

"Incoming WorkPool 3" - Thread [email protected] 
    java.lang.Thread.State: RUNNABLE 
    at java.awt.EventQueue.isDispatchThreadImpl(EventQueue.java:1024) 
    at java.awt.EventQueue.isDispatchThread(EventQueue.java:1014) 

To JDK 7.0.25, więc wydaje się jeden wątek jest zablokowany na

EventQueue next = eq.nextQueue; 
while (next != null) { 
    eq = next; 
    next = eq.nextQueue; 
} 

Istnieją dwa wątki AWT EventQueue , próbując zdobyć tę samą pushpoplock.

Maszyna wirtualna działa jako usługa, więc nie powinna próbować wykonywać zadań AWT, ale jest to wykonywane przez bibliotekę, z której korzystam.

Wszelkie pomysły? Czy mogę temu zapobiec?

Dzięki!

+0

1. Czy słyszałeś o SecondaryLoop, 2. ale "biorąc 100% procesora, ale najwyraźniej nic nie robiąc". mówiąc o JProfiler, 3. bez SSCCE/MCVE nie odpowiada, 4. 'java.awt.EventQueue.isDispatchThreadImpl (EventQueue.java: 1019) mówienie o isEventDispatchThread zwraca false' lub zdarzenia wykonane w EDT nie mają tam żadnego biznesu. 5. nie mam pojęcia, bez zdarzeń z bieżącego EDT lub wyjątku od RepaintManager – mKorbel

+0

1) Nie słyszałem wcześniej o SecondaryLoop. Sprawdziłem to, ale ja sam nie używam AWT, jest to biblioteka, która używa tej metody. 2) Nie użyłem JProfiler, użyłem JVisualVM, dostarczyłem mi wątek, który pokazałem fragmenty. 3) Nie mogę tego niestety odtworzyć. To był problem, który miałem w produkcji, wszystko, co mam, to zrzut wątku, więc nie mogę zapewnić SSCCE. 4-5) Obawiam się, że ich nie rozumiem. –

+1

Kto ustawia wartość eq.nextQueue na wartość null? Jeśli nikt go nie ustawi, pętla uruchomi się w nieskończoność, a CPU 100% będzie możliwe. Jeśli tak i jeśli zrobi to jakiś inny wątek, to sq.nextQueue powinno być niestabilne. Jeśli nie, ten wątek może nie wybrać wartości, ponieważ wątek może być buforowany wartością eq.nextQueue, w której pętla uruchomi się w nieskończoność, a procesor będzie w 100% możliwy. – Eranda

Odpowiedz

0

Twój problem jest związany z zakleszczeniem (see wikipeida).

Deadlock situation here Jak widać powyżej, swoje dwie EventQueues (tutaj R1 i R2) są w sytuacji impasu - każdy z nich twierdził jednego zasobu i nie może działać dalej podczas drugi zrobił domagać się innego zasobu. Obaj czekają na siebie bez końca.

Można rozwiązać ten problem z różnych podejść:

Spróbuj zmienić bibliotekę, masz rację, że biblioteka nie powinien starać się zrobić AWT rzeczy, jeśli nie jest to ściśle związane z biblioteki AWT. Istnieje wiele bibliotek na platformach takich jak github, jestem pewien, że znajdziesz inną bibliotekę, która zastąpi twoją, która powoduje błąd.

Jeśli możesz edytować swój kod, aby dodać monitorowanie, jesteś , aby zapobiec również zakleszczeniom.

synchronized(lock){ 
EventQueue next = eq.nextQueue; 
while (next != null) { 
    eq = next; 
    next = eq.nextQueue; 
} 
lock.notifyAll(); 
} 
+0

Powyższy kod jest częścią pakietu Java SDK (java.awt.EventQueue.isDispatchThreadImpl (EventQueue.java:1024)), nie ma możliwości, żebym mógł - lub chciałbym - zmienić ten kod. –

1

Czy istnieje możliwość, że push(EventQueue newEventQueue) nazywany jest przez program aplikacji i popycha ten sam EventQueue? Jeśli tak, to this i jego nextQueue będą tymi samymi obiektami i będą działać w nieskończonej pętli zużywającej procesor do 100%.

Ze stosu wynika, że ​​jest co najmniej jeden wątek. Więc nie jest to kwestia DEADLOCK.

Od wskazania 100% zużycia procesora i jego stanu jako RUNNABLE, co jest ewidentne, że wykonuje nieskończoną pętlę.

Kod może wejść do nieskończonej pętli wtedy i tylko wtedynextQueue ma wartość, która jest już w sieci (lub this). To może być problem z aplikacją. Dzięki.

+0

Nigdy o tym nie myślałem, ale jest to rzeczywiście możliwe, że biblioteka, której używam, robi to EventQueue.push. Nie jest to biblioteka open source, więc muszę się z nimi skontaktować. –