2013-07-30 38 views
5

Sıkışmış ve sonsuza dek çalışmaya devam edebilecek bir iş parçacığım var. Bu nedenle belirli bir süre sonra, çalışmayı durdurmayı, en sonunda temizlik yapmayı ve daha sonra ölmeyi tercih ederim. Bunu güvenli bir şekilde yapmak için nasıl giderim? Teşekkürler.Sonunda belirli bir süre geçtikten sonra son noktaya git

Bunun nasıl yapılacağına dair ilk düşüncem, bir çocuk ipliği yapmak ve uyuyarak temizlik yapmaktı. Ama sonra ana iş parçacığı hala çalışmayı deniyor ve bu yüzden bir hata verir.

+0

Bu iş parçacığında en üst düzey bir döngü var mı? İplik sıkışmış olsa bile tekrar tekrar ulaşılan bir kod parçası var mı? İş parçacığı çalışmaya başlamadan önce kaç kez döngü/yineleme olacağını tahmin edebilir misiniz? –

+0

İdeal olarak, iş parçanızın periyodik olarak kontrol ettiği bir işaretiniz olmalıdır. Bayrak ayarlanmışsa, iş parçacığınız, görevinin düzenli olarak kapatılmasını sağlamalıdır. – Aurand

+0

Döngü veya başka bir şey yoktur. İş parçacığı veri gönderiyor, ancak veri göndermek için çok uzun sürüyorsa kapatılmasını istiyorum. Bir kod satırında sıkışmışsa, periyodik olarak nasıl kontrol edebilirim? – user760220

cevap

3

Kodunuzu bir Callable haline getirin ve Gelecek için bir ExecutorService kullanın. Daha sonra, zamana göre yapılmayan bir zaman aşımı ile kullanın. Tam bir örnek için bkz. https://stackoverflow.com/a/2275596/53897.

+0

Geleceği tamamen unuttum. +1 –

+1

Bu, etkin dişin ölmesine neden olmaz. Sadece Future.get (uzun, TimeUnit) işlevini başlatan bekleyen ileti dizisi. Görev yürütülmeye devam ediyor. – yair

+0

Sonra yürütücünün kapatılmasını söyleyin. –

0

Engelleme çağrılarınız için zaman aşımlarını ayarlamanız gerekir. Zaman aşımı yoksa, çağrıyı soyutlayın ve bu şekilde zamanlayın.

Anketi tamamlanma durumu için 1 iş parçacığı oluşturabilir ve biraz aşıldıysa onu öldürebilirsiniz. Görevin kendisi yine başka bir iş parçacığı gerektirecekti. Bunu, staleness değerine sahip olan görevler oluşturarak yapardım. Tüm görevleri periyodik olarak yoklayın, eskiyenlerse iptal edin.

0

Öneri 1: Kodunuzu bir wait() ifadesiyle bir try bloğuna koyarsanız, son olarak izleyeceğiniz interruptedException'ı yakalayabilirsiniz. Başka bir iş parçacığı, iş parçacığınızın kesilmesi gereken durumlar olduğunda kesintiye neden olmak için bir notify() veya notifyAll() göndermelidir.

Öneri 2: Ben sadece Java ile yeni başlayan biriyim ama takılan iplik, try/finally bloğunuzun içine özel bir istisna atmanız gerektiği anlamına gelir.

+0

Eşzamanlı eklentileri Java 5'e ilginç bulabilirsiniz. Iş parçacığı doğrudan kullanarak% 100 doğru yapmak zor. –

0

(1)

iyi çözüm zaman aşımı ile verilerinizi göndermektir. Bu uygulanabilir değilse, böyle bir yapılandırma göstermiyor kullandığınız API, ikinci en iyi çözüm interruptible API kullanmak olacaktır çünkü

try { 
    mySendingDataLibraryApi.sendData(data, timeout /*, timeUnit */); 
     // some new APIs enable also to configure the time unit of the required timeout. 
     // Older APIs typically just use milliseconds. 
} catch (TimeoutException e) { 
    doCleanup(); // your cleanup method. 
} 

(2)

gibi görünmelidir sendData yöntemini yürütür ve yürütme iş parçacığını kesintiye uğratır. Bu, böyle bir kesintili API'nın sağlanmasına dayanır.

class MySendingDataRunnable implements Runnable {  
    @Override 
    public void run() { 
     try { 
      mySendingDataLibraryApi.sendDataInterruptibly(data); 
     } catch (InterruptedException e) { 
      doCleanup(); // your cleanup method. 
      // here either re-throw InterruptedExecption 
      // or restore the interrupted state with Thread.currentThread().interrupt(); 
     } 
    } 
} 

The: zamanlanmış yöntem API tarafından sağlanan değilse böyle bir yöntemin varlığına pek saymak olmaz ... Neyse, görevi yürütür dizisindeki kod gibi görünecektir

final ExecutorService executor = Executors.newSingleThreadExecutor(); 
final Future<?> future = executor.submit(new MySendingDataRunnable()); 
try { 
    final Object noResult = future.get(60, TimeUnit.SECONDS); // no result for Runnable 
} catch (InterruptedException e) { 
    // here again either re-throw or restore interupted state 
} catch (ExecutionException e) { 
    // some applicative exception has occurred and should be handled 
} catch (TimeoutException e) { 
    future.cancel(true); // *** here you actually cancel the task after time is out 
} 

(3: arayan kod iplik true ayarlanmış mayInterruptIfRunning bağımsız değişken ile görev istenilen bekleme süresi ve iptal etmek için, onun Future<?> submit(Runnable task) yöntemi tarafından döndürülen bir ExecutorService ve Future örneği kullanmak gerekir)

Kullandığınız API bu özelliklerden hiçbirini sağlamazsa (zamanlanmış/kesintili yöntemler), yaratıcılığınızı kullanmanız gerekir! Bu bir satırlık kod satırınız, numaralı kaynakta kodunu engelliyor olmalıdır. Bu kaynağa erişmeye çalışın ve kapatıp kapatmaya çalışın.Tipik bir örnek ağ bağlantısını kapatıyor.


Not: Yukarıdaki çözümler yalnızca gerçekten görevi iptal ve daha fazla görevler için iplik kurtararak bir yol sağlar. Ancak iş parçacığı hala yaşıyor olabilir. İş parçacığının öldürülmesi genellikle bir görev tamamlandığında (veya bu konuda başarısız olduğunda) yaptığınız bir şey değildir. Bir kez daha gerçekleştirilmemesi gereken belirli görevler için bazı thread (ler) oluşturduğunuzda kabul edilebilir. Bu gibi durumlarda, yukarıdaki ExecutorService'u kullanır ve shutdownNow() yöntemini çağırırsınız. Ve hatta shutdownNow() sadece en iyi çabayı ve tipik kesintisiz olarak fiili görev bağlıdır ...

Here's a detailed article (yine biraz eski ama).

İlgili konular