Bir catch InterruptException bloğunda Thread.currentThread.interrupt () neden çağrılsın?


Yanıtlar:


160

Bu durumu korumak için yapılır .

Eğer yakaladığımda InterruptExceptionve onu yutmak, aslında kesme fark herhangi üst düzey yöntemleri / iplik grupları önler. Hangi sorunlara neden olabilir.

Arayarak Thread.currentThread().interrupt(), iş parçacığının kesme bayrağını ayarlarsınız, böylece daha yüksek düzey kesme işleyicileri bunu fark eder ve uygun şekilde işleyebilir.

Uygulamada Java Eşzamanlılığı bunu daha ayrıntılı olarak Bölüm 7.1.3: Kesintiye Cevap Verme bölümünde tartışmaktadır . Kuralı:

Yalnızca bir iş parçacığının kesinti ilkesini uygulayan kod bir kesinti isteğini yutabilir. Genel amaçlı görev ve kütüphane kodu, kesinti isteklerini asla yutmamalıdır.


15
Gelen belgeler dile getirilmiştir Geleneksel olarak, herhangi bir yöntem atarak çıkışlar olduğunu" InterruptedException berraklaşır, durumunu kesmek o kadar yaptığında. Bunun açısından cevap net yapar düşünüyorum neden sen kesme durumunu korumak gerekir.
Stelios Adamantidis

Ayrıca , diğer "dağıtım mekanizması" aracılığıyla bu durum hakkında bildirim aldıktan sonra kesilen bayrağın ayarlanmasınıninterrupt() tek yolu olduğunu belirtmek gerekir. InterruptedException
sevo

67

Ben bu kod örneği şeyler biraz açık yapar düşünüyorum. İşi yapan sınıf:

   public class InterruptedSleepingThread extends Thread {

        @Override
        public void run() {
            doAPseudoHeavyWeightJob();
        }

        private void doAPseudoHeavyWeightJob() {
            for (int i=0;i<Integer.MAX_VALUE;i++) {
                //You are kidding me
                System.out.println(i + " " + i*2);
                //Let me sleep <evil grin>
                if(Thread.currentThread().isInterrupted()) {
                    System.out.println("Thread interrupted\n Exiting...");
                    break;
                }else {
                    sleepBabySleep();
                }
            }
        }

        /**
         *
         */
        protected void sleepBabySleep() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                //e.printStackTrace();
                Thread.currentThread().interrupt();
            }
        }
    }

Ana Sınıf:

   public class InterruptedSleepingThreadMain {

        /**
         * @param args
         * @throws InterruptedException
         */
        public static void main(String[] args) throws InterruptedException {
            InterruptedSleepingThread thread = new InterruptedSleepingThread();
            thread.start();
            //Giving 10 seconds to finish the job.
            Thread.sleep(10000);
            //Let me interrupt
            thread.interrupt();
        }

    }

Durumu geri ayarlamadan kesmeyi aramayı deneyin.


13
böylece sonuç ??
Scott 混合 理论

3
Teşekkürler. Şimdi ne demek istediğini anlıyorum: repl.it/@djangofan/InterruptedThreadExample
djangofan

20

Not:

http://download.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

Uzun süre bekleyen bir iş parçacığını nasıl durdurabilirim (örneğin, girdi için)?

Bu tekniğin çalışması için, bir kesinti istisnası yakalayan ve onunla başa çıkmaya hazır olmayan herhangi bir yöntemin istisnayı hemen yeniden gözden geçirmesi çok önemlidir. Yeniden anlatmak yerine tekrarlayıcılar diyoruz, çünkü istisnayı yeniden anlatmak her zaman mümkün değildir. InterruptedException özel durumunu yakalayan yöntemin bu (işaretli) özel durumu attığı bildirilmezse, aşağıdaki büyütme ile "kendini yeniden kesmesi" gerekir:

Thread.currentThread().interrupt();

Bu, iş parçacığının mümkün olan en kısa sürede InterruptedException özel durumunu yeniden oluşturmasını sağlar.


2

Kötü bir uygulama ya da en azından biraz riskli olduğunu düşünürdüm. Genellikle daha üst düzey yöntemler engelleme işlemleri gerçekleştirmez ve asla InterruptedExceptionorada görmezler . Kesilebilir işlem yaptığınız her yerde maskelerseniz, bunu asla alamazsınız.

Thread.currentThread.interrupt()Başka bir istisna veya sinyal kesme isteği başka herhangi bir şekilde yükseltmemenin tek nedeni (örn interrupted. Bir iş parçacığının ana döngüsünde yerel değişken değişkeni ayarlamak ), finallybloklar gibi istisna ile gerçekten hiçbir şey yapamayacağınız durumdur .

Thread.currentThread.interrupt()Görüşmenin sonuçlarını daha iyi anlamak istiyorsanız Péter Török'ün cevabına bakınız .


0

Java doc'den bakın

Bu iş parçacığı wait (), join (), sleep (long) çağrısında engellenirse, kesme durumu silinecek ve bir InterruptedException alacaktır.

Bu iş parçacığı bir G / Ç işleminde engellenirse, iş parçacığının kesme durumu ayarlanır ve iş parçacığı ClosedByInterruptException alır.

Bu iş parçacığı bir Seçicide engellenirse, iş parçacığının kesme durumu ayarlanır ve seçim işleminden hemen geri döner.

Önceki koşullardan hiçbiri geçerli değilse, bu iş parçacığının kesme durumu ayarlanır.

Bu nedenle, @Ajay George'daki sleepBabySleep () yöntemini değiştirirseniz G / Ç işlemine veya yalnızca bir çıkışa yanıt verirseniz, programı durdurmak için durumu geri ayarlamanız gerekmez. (BTW, InterruptedException bile atmıyorlar)

Tıpkı @ Péter Török'ün söylediği gibi => Bu durumu korumak için yapılır. (Ve özellikle InterruptedException özel durumunu atacak yöntem için)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.