7

İşlemleri çalıştırmak için ProcessBuilder kullanıyorum. Girdi/Çıktı akışlarını, bunları bir iş parçacığı havuzunda (Executors.newCachedThreadPool()) ele alarak ilgili runable'ları göndererek hallediyorum.
Sonuç aldım ama her şimdi ve sonra hiçbir şey alamıyorum.
Örneğin, işlemci üreticisi için cmd \C dir, dir sonuçlarını geri alıyorum ama bazen hiçbir şey alamıyorum (buna rağmen sonuç process.getInputStream'u işleyen runnable'dan geri dönüyor gibi görünüyor).
Bunu nasıl ayıklayabilirim? Müdahale ediyor. Aynı kod ile ben new Thread(runnable).start() yaptığımda herhangi bir sorun yoktu. Bir iş parçacığı havuzuna geçtikten sonra gerçekleşmeye başladı.Bir işlemin beklenmesi ve akış okunması arasındaki eşzamanlılık sorunu?

Güncelleme:
ben bir şey buldum: Ben Runnable aşağıdaki do
: Bu Finished reading 521 yazdırır çalışmıyor durumlarda

try { 
    while ((line = br.readLine()) != null) { 
      pw.println(line); 
       sb.append(line); 
    } 
    System.out.println("Finished reading "+sb.length()); 
} catch (IOException e) {    
    e.printStackTrace(); 
} 
finally{ 
    pw.flush();  
    try{ 
    isr.close(); 
    }catch(Exception e){} 
} 

. Ancak sonucu aracılığıyla ve sb değil deneyin.
pw olduğunu PrintWriter pw = PrintWriter (OutputStream); `Ben çalıştırılabilir

Güncelleme 2 geçmek hangi:
O görünüyor: status = process.waitFor(); döner önceki inputStream bitirir ele katedilebilen önce. Bu nasıl olabilir?
javadoc:
the calling thread will be blocked until the subprocess exits'da okurum. Yani bu, I/O akışlarını tüketmeden önce 'u iade edebildiğim anlamına mı geliyor?

Güncelleme 3:
Ruby
yani burada aynı sorunu gibi görünüyor süreç Gösterge Çıkışı

+0

Bir işlem başka bir işlemi çağırırsa, ilk işlem erken dönebilir - normal davranış. – Sebastian

+0

Bu erken geri dönüş hakkında değil.It çıkışı hakkında * budur * Çıkış akımları tükendi – Jim

cevap

1

Evet biten ve tüketen arasında bazı yarış durumu vardır. işlemler arasındaki stdio, arabelleğe alınır (genellikle 4 KB arabellek). Proses tampona yaz ve var. B işleminde iki iplik vardır; biri A'nın sonuna kadar bekler ve diğeri A'dan gelen çıktıyı okur. Önce hangi iş parçacığının yürütüldüğünden emin olmanın bir yolu yoktur.

Yani bu mümkün process.waitFor(); döner önce tüm tamponlu çıktı okunduğunu (çıktının çok olduğunda bile muhtemeldir).

Yıkama işleminin, A'nın herşeyi yazdığından emin olmasını sağladığından, buradaki temizleme işleminin işe yaramadığını unutmayın. Verileri benzer şekilde okumak için "zorlamak" B'nin bir yolu yoktur.

Bu nedenle, çıkış durumu hatırlar ve giriş akışından EOF okumak yalnızca "tam sonlandırıldı" olarak süreci dikkate almalıdır.

DÜZENLEME bir çözüm daha sonra uygulamakla boyun ve sonucu (lar) almak için Future API (example) kullanabileceği bir Callable içine gobbler akışı baba hindi içine waitFor() taşımak ve dönüştürmek olacaktır.

+0

Bu yüzden nasıl işlemek için kodumu değiştirmeliyim? Ben sadece 'waitFor' yapmak ve akış okuyucumda kodu yayınlanmıştır – Jim

+1

Çağrı "waitFor" ve ardından stream işleyicisini içeren thread üzerinde join() '. Ya da akış işleyicisinin her ikisini de aynı yere sahip olmak için 'while()' döngüsünün dışında waitFor() işlevini çağırın. –

+0

1) Aktarım işleyicisi bir yürütücüye gönderilir. Nasıl yapabilirim? 2) Akış işleyici nasıl "waitFor" diyebilir? Sonuç, işlemin bitmesini bekleyen iş parçacığına iletilmesi beklenir – Jim