簡體   English   中英

我想隨時停止線程

[英]Stop thread anytime i want

我有一個方法,應該中斷一個線程,但事實並非如此。 是否需要一直檢查while方法中中斷的線程來停止線程? 我怎樣才能隨時終止線程?

solverTh = new Thread(new Runnable() {
        @Override
        public void run() {
            while(somethingistrue){
                //do lot of stuff here for long time
            }
        }
    });
    solverTh.start(); 
}

public void terminate(){
    if(solverTh != null){
        solverTh.interrupt();
    }
}

好吧,我認為“很多東西”無關緊要,但我會發布它。 它進行了 openGL 次操作,我將 boolean 變量“終止”添加到它現在工作的代碼中,我只是想找到一個更好的解決方案:(glc 是一個 GLCanvas,rotmultiplecube 方法旋轉 3 個對象)無論如何我已經解決了這個問題現在,感謝您的回答。

            terminated = false;
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                Logger.getLogger(BruteForce.class.getName()).log(Level.SEVERE, null, ex);
            }

            int colorToBeSolved = Statics.RED_BLUE_TABLE[stateToBeSolved];
            System.out.println(stateToBeSolved + "," + colorToBeSolved);
            if(entities[0].getColor() != colorToBeSolved){
                if(terminated) return;
                fullRotate(Statics.FIRST_ROW, Statics.DOWN);
            }
            if(entities[1].getColor() != colorToBeSolved){
                if(terminated) return;
                fullRotate(Statics.SECOND_COL, Statics.RIGHT);
            }
            if(entities[2].getColor() != colorToBeSolved){
                if(terminated) return;
                fullRotate(Statics.THIRD_COL, Statics.RIGHT);
            }
            if(entities[3].getColor() != colorToBeSolved){
                if(terminated) return;
                fullRotate(Statics.SECOND_ROW, Statics.DOWN);
            }
            if(entities[6].getColor() != colorToBeSolved){
                if(terminated) return;
                fullRotate(Statics.THIDR_ROW, Statics.DOWN);
            }

            for(int i = 0; i < 9; ++i){
                int col = i % 3;
                int row = 3 + i/3;
                while(entities[i].getState() != stateToBeSolved){
                    for(int j = 0;j < 2; ++j){
                        if(entities[i].getState() != stateToBeSolved){
                            if(terminated) return;
                            fullRotate(col, Statics.LEFT);
                            if(terminated) return;
                            fullRotate(row, Statics.UP);
                            if(terminated) return;
                            fullRotate(col, Statics.RIGHT);
                            if(terminated) return;
                            fullRotate(row, Statics.DOWN);
                        }
                    }
                    for(int j = 0;j < 2; ++j){
                        if(entities[i].getState() != stateToBeSolved){
                            if(terminated) return;
                            fullRotate(col, Statics.RIGHT);
                            if(terminated) return;
                            fullRotate(row, Statics.UP);
                            if(terminated) return;
                            fullRotate(col, Statics.LEFT);
                            if(terminated) return;
                            fullRotate(row, Statics.DOWN);
                        }
                    }
                }
            }
        }

和全旋轉方法:

private void fullRotate(int selectionIndex, int direction){
    for(int i = 0; i < 9; ++i){
        glc.rotMultipleCubeSlow(selectionIndex, direction);
        try {
            Thread.sleep(20);
        } catch (InterruptedException ex) {
            terminate();
        }
    }
    glc.setMovesText(selectionIndex, direction);        
    glc.setMultipleStateAndColorsByTable(selectionIndex, direction);
    glc.isEntitiesRight();
}
while(somethingistrue !Thread.currentThread().isInterrupted()){
  //do lot of stuff here for long time
}

不必為阻塞 IO 工作。使用骯臟的技巧:覆蓋 Thread.interrupt() 關閉 IO object,導致 IOException 如果處理得當可能會結束線程運行方法。

優雅的解決方案是修改您的 fullRotate() 方法以拋出 InterruptedException。

private void fullRotate(int selectionIndex, int direction)
       throws InterruptedException{
    for(int i = 0; i < 9; ++i){
        glc.rotMultipleCubeSlow(selectionIndex, direction);
        Thread.yield();
    }
    glc.setMovesText(selectionIndex, direction);        
    glc.setMultipleStateAndColorsByTable(selectionIndex, direction);
    glc.isEntitiesRight();
}
  • 當您調用 Thread.interrupt() 時,當任何拋出它的方法被調用時,您會導致 InterruptedException,在您的情況下是 Thread.sleep() 或 Thread.yield()。 這意味着最好的方法是使用它來實際中斷計算。
  • 你仍然需要檢查 Thread.currentThread().isInterrupted() 如果你想立即響應你的 Thread.interrupt()
  • 您可以刪除 if(terminated) return; 或者將其替換為 Thread.currentThread().isInterrupted() 檢查。 刪除會很好,因為 fullRotate() 中的 Thread.sleep(20)/Thread.yield() 將拋出 InterruptedException。 如果沒有所有這些 if(terminated) 到處都是,代碼也會更清晰。
  • 使用 Thread.yield() 代替 Thread.sleep(20)。 顯然你不想睡覺,因為你放了 20 毫秒。 20 milis 非常接近上下文切換時間量程。 線程將更多或更少地休眠。 你不希望它無緣無故地睡得更多,所以使用 yield()。

你的線程 run() 然后變成:

solverTh = new Thread(new Runnable() {
    @Override
    public void run() {
        while(somethingistrue && 
              !Thread.currentThread().isInterrupted()) {
            try {
                //do lot of stuff here for long time
            } catch (InterruptedException ex) {
                // handle stop processing 
            }
        }
    }
});
solverTh.start(); 

還必須從以下內容中刪除try catch:

        try {
            Thread.sleep(2000);
        } catch (InterruptedException ex) {
            Logger.getLogger(BruteForce.class.getName()).log(Level.SEVERE, null, ex);
        }

中斷線程的唯一方法是讓它自己退出。 由於死鎖的可能性,在 Java 中甚至沒有實現直接中斷。 所以你的線程代碼必須是這樣的:

solverTh = new Thread(new Runnable() {
    @Override
    public void run() {
        while(somethingistrue) 
            // Do a little stuff here
        }
    }
});
solverTh.start(); 

somethingistrue是線程中斷的一種信號。

唯一可以可靠地停止一個線程從另一個線程執行的是操作系統。 所以,選擇不多:

1) 向線程發出停止自身的信號。 這個方案有點取決於線程在做什么。 如果它在另一個處理器上運行或卡在無法解除阻塞的阻塞調用上(請注意,可以說服許多阻塞調用提前返回),可能會出現問題。

“很多東西”在做什么?

2) 使用操作系統調用終止線程。 這可能是一個可行的選擇,具體取決於線程的作用。 如果有任何可能在線程持有重要資源的公共鎖時終止線程(例如,它在 malloc() 的中間並且已鎖定內存管理器),那么您可能會遇到麻煩。 您必須確定線程正在做什么才能以這種方式安全地中止它。

3)使用單獨的進程來運行“東西”。 這顯然可以正常工作,但通常涉及緩慢而痛苦的進程間通信來傳遞數據和返回結果。

4)設計應用程序,使其不需要終止線程。 有些應用程序不需要終止任何線程,除非在應用程序關閉時,所以沒有問題——操作系統可以停止任何東西。 在應用程序運行期間必須“停止”線程並且正在運行長時間的 CPU 密集型操作或被阻塞很長時間且可能不確定的情況下,通過將線程的優先級設置為最小/空閑來“孤立”線程讓它最終消亡是另一種常見的方法。

最糟糕的情況是一個線程長時間運行大量的東西,它使用內存管理器或其他公共鎖,可能在一個你不知道它在做什么的庫中,不能被掛鈎和讀/寫以“孤立”它的方式處理數據意味着無法啟動另一個線程來使用該數據。 你真的很笨,你可能不得不終止應用程序並重新啟動。 最好避免線程可以進入這樣的 state 的設計:)

5) 忘記了 - 如果線程正在使用您可以獲得的數據,將某些內容設置為 NULL、0、MaxInt 或其他類似 bodge 的內容可能會導致在運行長內容的線程中引發異常。 當執行從長內容中冒出來時,線程可以檢查異常處理程序中的中斷 state 並在設置時退出。

當線程正在運行(消耗 CPU 周期)時,默認情況下它不會(自動)響應Thread.interrupt() 您將必須編寫代碼來明確地執行此操作。

//do lot of stuff here for long time分成 2 個或更多步驟,並在這些步驟之間插入檢查Thread.currentThread().isInterrupted() - 如果為真 - 中斷,否則繼續。 這是實現您想要的唯一安全方法。

這取決於長期運行的東西是什么,您將必須設計步驟並決定何時最好檢查中斷和突破。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM