2016-04-22 83 views
0
"Star Builder 129" daemon prio=10 tid=0x00007f41bd8f6000 nid=0x152b0 waiting on condition [0x00007f445cd1a000] 
    java.lang.Thread.State: TIMED_WAITING (parking) 
     at sun.misc.Unsafe.park(Native Method) 
     - parking to wait for <0x00007f59c9e1c278> (a java.util.concurrent.FutureTask) 
     at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226) 
     at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:422) 
     at java.util.concurrent.FutureTask.get(FutureTask.java:199) 

我花了最後一天的時間試圖理解這實際上是什麼意思。沒有足夠的信息,或者我找不到任何有用的信息。分析java線程轉儲

「等待條件」是什麼意思?我們在監視器上等着嗎? 「0x00007f445cd1a000」表示什麼?

「停車等待」是什麼意思?什麼是「0x00007f59c9e1c278」?

的源代碼:

 List<FutureTask<List<FileStatus>>> tasks = new LinkedList<FutureTask<List<FileStatus>>>(); 
    for(int idx = 0, len = Math.max(1,numberOfThreads()); idx < len; ++idx) { 
     StatusWorker worker = new StatusWorker(this, qualifiedPath, userFilter, prefixQueue, prefixCounter, statusCounter); 
     FutureTask<List<FileStatus>> task = new FutureTask<List<FileStatus>>(worker); 
     threadPool.execute(task); 
     tasks.add(task); 
    } 

    try { 
     List<FileStatus> statuses = new LinkedList<FileStatus>(); 

     for(FutureTask<List<FileStatus>> task : tasks) { 
      statuses.addAll(task.get(FILE_LISTING_TIMEOUT, TimeUnit.SECONDS)); 
      logger.debug("Result from task [{}]", task); 
     } 
+0

TD中應該存在第二個「0x00007f59c9e1c278」事件。這是做一些行動,線程等待,直到這個動作完成。這表示像紅綠燈一樣的鎖。等到你可以運行(紅到綠開關)。 – Konrad

+0

這就是我檢查的第一件事情,在TD中不存在具有此ID(「0x00007f59c9e1c278」)的其他線程。一些線程可以放在jstack輸出中嗎? – ajaymysore

+0

您使用的是哪個JDK版本? –

回答

2

這可能指向編碼問題。代碼等待FutureTask的尚未執行完成。

查找片段下面的示範

Future.java

import java.util.concurrent.Callable; 
import java.util.concurrent.FutureTask; 
import java.util.concurrent.TimeUnit; 

public class Future { 

    public static void main(String[] args) throws Exception { 
     FutureTask<String> future = new FutureTask<>(
       new Callable<String>() { 
        @Override 
        public String call() throws InterruptedException { 
         return "foo"; 
        } 
       }); 
     String get = future.get(30, TimeUnit.SECONDS); 
     System.out.println("get = " + get); 
    } 
} 

在會話中運行1

javac Future.java 
java Future 

運行在會話2

$ jps 
... 
12345 Future 
jstack -l 12345 > jstack.12345.log 

注:12345是運行java Future進程的PID jstack.12345.log

"main" #1 prio=5 os_prio=0 tid=0x000000000273b000 nid=0x2b24 waiting on condition [0x0000000002abf000] 
    java.lang.Thread.State: TIMED_WAITING (parking) 
     at sun.misc.Unsafe.park(Native Method) 
     - parking to wait for <0x0000000781973910> (a java.util.concurrent.FutureTask) 
     at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215) 
     at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:426) 
     at java.util.concurrent.FutureTask.get(FutureTask.java:204) 
     at Future.main(Future.java:19) 

編輯基於所張貼的代碼的

內容片段中的描述情況可以很容易地發生。參照下面的代碼Executor.execute

在將來某個時候執行給定的命令。

at some time in the future這意味着立即在execute調用。因此,在任務實際執行之前,您可能會到達線路task.get(...)。您的線程池也可能無法同時運行numberOfThreads()線程。

一個小例子,演示(運行如前所述的相同命令)。我們創建一個只能執行一個任務的線程池。我們將兩個任務分配給該池。在爲這兩項任務調用executor.execute(..)之後,我們立即等待第二項任務的結果。由於第一項任務是長期的,我們會逐步進入你發現的情況。

Future.java

public class Future { 

    public static void main(String[] args) throws Exception { 
     FutureTask<String> future1 = new FutureTask<>(
       () -> { 
        System.out.println("future1"); 
        TimeUnit.SECONDS.sleep(50); 
        return "finished future1"; 
       }); 

     FutureTask<String> future2 = new FutureTask<>(
       () -> { 
        System.out.println("future2"); 
        return "finished future2"; 
     }); 

     ExecutorService executor = Executors.newFixedThreadPool(1); 
     executor.execute(future1); 
     executor.execute(future2); 

     String get = future2.get(30, TimeUnit.SECONDS); 
    } 
} 

內容jstack.12345的。登錄

"pool-1-thread-1" #9 prio=5 os_prio=0 tid=0x00007ff50811c000 nid=0x5a5c waiting on condition [0x00007ff4e7365000] 
    java.lang.Thread.State: TIMED_WAITING (sleeping) 
    at java.lang.Thread.sleep(Native Method) 
    at java.lang.Thread.sleep(Thread.java:340) 
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386) 
    at concurrent.Future$1.call(Future.java:19) 
    at concurrent.Future$1.call(Future.java:15) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
    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) 

"main" #1 prio=5 os_prio=0 tid=0x00007ff50800a000 nid=0x5a4d waiting on condition [0x00007ff50e314000] 
    java.lang.Thread.State: TIMED_WAITING (parking) 
    at sun.misc.Unsafe.park(Native Method) 
    - parking to wait for <0x00000000ec03dda8> (a java.util.concurrent.FutureTask) 
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215) 
    at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:426) 
    at java.util.concurrent.FutureTask.get(FutureTask.java:204) 
    at concurrent.Future.main(Future.java:36) 

pool-1-thread-1 - 是目前睡(模擬長時間運行的任務)

mainfuture1轉儲 - 是轉儲future2.get(30, TimeUnit.SECONDS),它等待的future2的結果,這實際上是還沒開始。

+0

我們確實在未來調用執行。粘貼了代碼。 – ajaymysore

+0

@ajaymysore如果您在awaitDone狀態中看到任務,那麼它尚未完成。您應該看到轉儲中的其他線程仍在執行一個或多個任務。 –

+0

@ajaymysore看看我更新的答案。您發佈的代碼很容易導致您發現的情況。 – SubOptimal

1

應該更好地記錄Oracle熱點JVM上的線程轉儲(一個出色的調試工具),以便解答這些問題的答案,但基本上基於Java對多線程的內置支持。這裏是我對你的問題的看法:

「等待條件」是什麼意思?

總之,這意味着有問題的線程在關聯的監視器上調用了Object.wait()方法。

Java的併發支持的一個主要特徵是名爲wait/notify的低級構造,它被用作某種車間用於線程間通信。當線程正在使用共享可變狀態時,在一個線程安全的程序中,它們應該確保該狀態在對它進行操作之前滿足某些條件(狀態)。

經典生產者 - 消費者模式中的一個示例是消費者線程等待某個共享隊列至少有一個消耗項目。因此,對於消費者線程來做任何有意義的工作,它依賴於其他(例如生產者)線程來產生項目。爲了使這個工作正常,消費者線程進入隊列中的監視器(進入關鍵部分,保持排他鎖),但隨後在某些情況下旋轉(應該有一個while循環)爲真。

如果條件是假的,它會立即放棄鎖在顯示器上(退出顯示器)並請求以某種方式記住,當下次JVM挑選一個線程進入相同顯示器。你看,沒有放棄鎖定,就沒有進展。與顯示器關聯的Java implements this via the notion of a wait-set

我們是否在監視器上等待?

號上等待,或者說等待進入監視器會正在等待線程。下面是這樣的(阻塞)的線程的線程轉儲片段看起來像:

"thread2" #12 prio=5 os_prio=31 tid=0x00007ff51607d000 nid=0x5903 waiting for monitor entry [0x000000012f693000] 
    java.lang.Thread.State: BLOCKED (on object monitor) 
    at juc.SyncRace$Lock.sleep(SyncRace.java:11) 
    - waiting to lock <0x000000076b021630> (a java.lang.Class for juc.SyncRace$Lock) 

在這個例子中轉儲,該線程thread2希望目前獲得鎖(在線程轉儲的時間)從其他線程持有。這使得thread2進入BLOCKED state

「0x00007f445cd1a000」表示什麼?

它表示線程正在等待成爲真的條件變量

「停車等待」是什麼意思?什麼是「0x00007f59c9e1c278」?

的所有線程條件變量等待成爲真正有線程轉儲一個非常類似的期待片段。實際的等待支持通過LockSupport.park()Unsafe.park執行。 (我不確定是什麼0x00007f59c9e1c278是)。