簡體   English   中英

給定兩個Java線程,當其中一個線程完成時停止一個線程

[英]Given two Java threads, stop one thread when one of them finishes

我正在為這個問題尋找一個干凈的設計/解決方案:我有兩個線程,可以在用戶想要的時候運行,但最終在用戶發出stop命令時停止。 但是,如果其中一個線程突然結束(例如,由於運行時異常),我想停止另一個線程。

現在兩個線程都執行一個Runnable (所以當我說'停止一個線程'我的意思是我在Runnable實例上調用一個stop()方法),我在想的是避免使用線程(Thread類)並使用CompletionService接口然后將兩個Runnables提交給此服務的實例。

有了這個,我會使用CompletionService的方法take() ,當這個方法返回時,我會停止兩個Runnables,因為我知道它們中至少有一個已經完成。 現在,這有效,但如果可能的話,我想知道一個更簡單/更好的解決方案。

另外,當我們有n線程時,只要其中一個線程完成停止執行所有其他線程,什么是一個好的解決方案?

提前致謝。

沒有Runnable.stop()方法,所以這是一個明顯的非首發。

不要使用Thread.stop() 絕大多數情況下,它基本上是不安全的。

如果正確實施,以下是一些應該有效的方法。

  1. 您可以讓兩個線程定期檢查一些常見的標志變量(例如,將其stopNow ),並安排兩個線程在完成時設置它。 (標志變量需要是易失性的......或者是正確同步的。)

  2. 您可以讓兩個線程定期調用Thread.isInterrupted()方法以查看它是否已被中斷。 然后每個線程在完成時需要在另一個線程上調用Thread.interrupt()


我知道Runnable沒有那個方法,但是我傳遞給線程的Runnable的實現確實有它,並且當調用它時,運行器將完成run()方法(類似於Corsika的代碼,在這個答案之下)。

據我所知,Corsika的代碼假定有一個stop()方法可以在調用時做正確的事情。 真正的問題是你是如何實現它的? 或者你打算如何實現它?

  • 如果您已經有一個可行的實現,那么您就可以找到問題的解決方案。

  • 否則,我的回答提供了兩種可能的方法來實現“立即停止”功能。

我感謝您的建議,但我有疑問,“定期檢查/致電”如何轉換成代碼?

它完全取決於Runnable.run()方法執行的任務。 它通常需要在某些循環中添加檢查/調用,以便經常合理地進行測試......但不要太頻繁。 您還想檢查何時可以安全地停止計算,這是您必須自己解決的另一件事。

以下內容應該有助於您了解如何將其應用於您的問題。 希望能幫助到你...

    import java.util.*;

    public class x {

        public static void main(String[] args) {

            ThreadManager<Thread> t = new ThreadManager<Thread>();
            Thread a = new MyThread(t);
            Thread b = new MyThread(t);     
            Thread c = new MyThread(t);
            t.add(a);
            t.add(b);
            t.add(c);
            a.start();
            b.start();
            c.start();      
        }
    }

    class ThreadManager<T> extends ArrayList<T> {

        public void stopThreads() {
            for (T t : this) {
                Thread thread = (Thread) t;
                if (thread.isAlive()) {
                    try { thread.interrupt(); } 
                    catch (Exception e) {/*ignore on purpose*/}
                }
            }
        }
    }

    class MyThread extends Thread {

        static boolean signalled = false;

        private ThreadManager m;

        public MyThread(ThreadManager tm) {
            m = tm;
        }

        public void run() {
            try {           
                // periodically check ...
                if (this.interrupted()) throw new InterruptedException();
                // do stuff
            } catch (Exception e) {
                synchronized(getClass()) {
                    if (!signalled) {
                        signalled = true;
                        m.stopThreads();
                    }
                }
            }
        }
    }

無論您使用停止標志還是中斷,您都需要定期檢查線程是否已發出停止信號。

你可以讓他們互相訪問,或者回訪一下可以訪問兩者的東西,這樣就可以打斷另一個。 考慮:

MyRunner aRunner = new MyRunner(this);
MyRunner bRunner = new MyRunner(this);
Thread a = new Thread(aRunner);
Thread b = new Thread(brunner);


// catch appropriate exceptions, error handling... probably should verify
// 'winner' actually is a or b
public void stopOtherThread(MyRunner winner) {
    if(winner == aRunner ) bRunner .stop(); // assumes you have stop on class MyRunner
    else aRunner.stop();
}

// later
a.start();
b.start();


// in your run method
public void run() {
    // la de da de da
    // awesome code
    while(true) fork();
    // other code here
    myRunnerMaster.stopOtherThread(this);
}

暫無
暫無

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

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