2016-01-03 101 views
3

我有以下代碼線程和中斷

package threads; 

import java.util.ArrayList; 
import java.util.List; 

public class Threads extends Thread implements Runnable { 

    private final List<Thread> threadList = new ArrayList<>(); 
    private String f, l; 
    private Thread greetings1, greetings; 

    public static void main(String[] args) { 

     String[] elements = { "Tim", "Fred", "Jeff", "Scott" }; 
     Threads t = new Threads(); 
     for (String e : elements) { 
      t.threadL(e); 

      t.threadR(e); 
     } 

     for (int index = 0; index < t.threadList.size(); index++) { 
      // blank at the moment 

     } 
    } 

    public void threadR(String f) { 
     greetings = new Thread(f); 

     Thread greetingsFromFred = new Thread(greetings) { 

      @Override 
      public void run() { 
       for (int i = 1; i < 5; i++) { 
        try { 
         System.out.println("Main Thread: " + i + " " + f); 
         Thread.sleep(5000); 

        } catch (InterruptedException ex) { 
         System.out.println("Main thread interrupted."); 

        } 
        System.out.println("Main thread exiting."); 
       } 
      } 
     }; 
     greetingsFromFred.start(); 
    } 

    public List<Thread> threadL(String l) { 
     greetings1 = new Thread(this); 

     this.l = l; 
     greetings1.start(); 

     threadList.add(greetings1); 

     return (threadList); 

    } 

    @Override 
    public void run() { 

     greetings.interrupt(); // interrupt greetings thread here <------- 

     System.out.println("Greetings from " + l + "! threadL"); 

    } 
} 

當線程1運行我想從運行中斷threadR並因此導致

System.out.println("Main thread interrupted."); 

從threadR

我有印刷在我的代碼高亮顯示,其中中斷應該發生

greetings.interrupt(); //interrupt greetings thread here <------- 

爲什麼中斷不能正常工作?

+3

請修正您的代碼中的縮進;目前它是無法讀取的。 –

+0

你的意思是「中斷不能像目前那樣工作」? –

+1

「擴展了Thread implements Runnable」我建議你在其中之一中進行選擇。 – MeetTitan

回答

3

你的程序有點迷宮般的線程對象。我們試着從main開始。

main中,您將創建一個對象t,該對象的類型爲Threads。這意味着它是一個Thread和一個Runnable

然後,對於每個字符串,運行tthreadLthreadR並將該字符串作爲參數。

沒有在main你確實開始t,甚至直接運行它的run方法。

然後,在threadR中,創建一個新的空的Thread並將其分配給greetings

然後,您使用的是新的空Thread(問候)做爲所被傳遞到一個新的Thread對象,它也有它的run方法重寫一個Runnable。這是徒勞的。無論如何,greetingsFromFred已啓動,並會運行循環。但greetings仍然包含有無關的greetingsFromFred縷空Thread

threadL創建另一個Thread,給你傳遞當前Thread(這是在maint)作爲其運行的。然後,你終於開始了。它會嘗試中斷greetings中的線程,但正如我們所說,這是一個從未啓動的非活動空線程。

你的結構應該比少了很多令人費解。儘可能使用Runnable對象來執行應該執行的操作。因此,Threads本身shoudld是Runnable,並threadR或許應該被固定到這樣的事情:

public void threadR(String f) { 

    Runnable greetingsFromFred = new Runnable() { 

     @Override 
     public void run() { 
      for (int i = 1; i < 5; i++) { 
       try { 
        System.out.println("Main Thread: " + i + " " + f); 
        Thread.sleep(5000); 

       } catch (InterruptedException ex) { 
        System.out.println("Main thread interrupted."); 

       } 
       System.out.println("Main thread exiting."); 
      } 
     } 
    }; 

    greetings = new Thread(greetingsFromFred, f); 
    greetings.start(); 
} 

這樣,greetings將是一個Thread這將運行一個您已經創建了一個Runnable這個循環,也有名字f

但是請注意,由於您實際上並未停止catch子句中的循環,因此當線程中斷時不會退出循環,並且可能會多次打印「正在退出」消息,取決於中斷何時到達循環。

+0

@ RealSkeptic我正在嘗試線程 - 我對線程相當陌生,只是看着我可以做的不同事情。您的導遊對我瞭解正在發生的事情非常有用,而且我還沒有開始問題線索,這是主要問題。來自你的偉大答案 – Ingram

0

你需要中斷greetingsFromFred。這是正在啓動並實際運行的線程。線程greetings永遠不會運行。是隻作爲可運行的傳遞給另一個線程。爲什麼你甚至會在線程的構造函數中傳遞其他線程?這整個設計很腥。我認爲你對thread/runnable以及何時以及如何使用它感到困惑。

0

要中斷的線程稱爲greetingsFromFred而不是greetings所以如果您使greetingsFromFred可見,此更改將起作用。

 greetingsFromFred.interrupt(); //interrupt greetings thread here <------- 
0

正如其他人所指出的,這裏還有幾個問題。

不必要的繼承

Threads類有一個run()方法中斷線程的任何分配給greetings,但也RL繼承run()方法。 R延伸Thread和覆蓋run(),並L只是延長Thread沒有覆蓋。那個結構沒有意義。

鑑於此,似乎run()方法應該被L覆蓋。

如果你做到了這一點,那麼就不需要Threads覆蓋Thread或者執行Runnable。你完全可以採取關閉,有RL每個覆蓋Thread自己(使用Thread(String)構造函數)。

public class Threads { 
... 
    public List<Thread> threadL(String l) { 
     greetings1 = new Thread(l) { 
      @Override 
      public void run() { 
       greetings.interrupt(); // interrupt greetings thread here <------- 
       System.out.println("Greetings from " + l + "! threadL"); 
      } 
     ... 
    } 
} 

所以現在threadR()創建並啓動一個新的Thread將被打斷,threadL()創建並啓動一個新的Thread將中斷和Threads只是存在的main()方法和threadR()線程的創建/啓動和threadL()。清潔器。

中斷錯誤的線程

正如其他人所指出的,你有這種不必要的變量,greetingsFromFred,這只是事情複雜化。您greetingsFromFred所做的一切,你應該不是爲greetings做(除了構造函數)。在greetings

public void threadR(String f) { 
    greetings = new Thread(f) { 

     @Override 
     public void run() { 
      ... 
     } 
    greetings.start(); 
} 

競爭條件下面是最細微的部分,IMO。您使用的是靜態變量greetings來保存當前Thread對象R,目前L應該中斷。但是這兩個線程之間沒有協調。我們沒有理由相信,每個L會看到一個獨特的Rgreetings。這是一個非常糟糕的事情。你需要做的是使greetingsvolatile,然後使R等待,直到greetings爲空之前分配它,並使L等待,直到greetings不中斷之前,中斷它。

private volatile Thread greetings; 
... 
public void threadR(String f) { 
    while (greetings != null); 
    greetings = new Thread(f) { 
... 
public void threadL(String l) { 
    Thread greetings1 = new Thread(l) { 
     @Override 
     public void run() { 
      while (greetings == null); 
... 

請注意使用while(...);。尾隨分號是一個空的語句。這個結構只是說要不斷檢查條件,直到它是假的,然後繼續。由於R永遠不會繼續,直到它有一個null然後設置它,並且L永遠不會繼續,直到它有一個non-null然後將其置爲空,它們將始終保持同步。