2015-04-23 81 views
1

嗨,我正在學習和玩java中的線程。我在一本書中看到Thread對象和Running Thread不是同一件事。即使線程完成它的運行方法,運行線程也會進入死亡狀態,我甚至用isAlive()方法檢查它。我想知道,如果兩者都不同,那麼下面的代碼不能按照我的理解工作。Java線程對象vs正在運行線程

public class Main { 

    public static void main(String[] args) throws ParseException { 
     Student s = new Student(); 

     Thread t = new Thread(s); 

     t.start(); 
     t.run(); 
     t.run(); 
     t.run(); 

     t.run(); 
     t.run(); 

    } 
} 

class Student implements Runnable { 
    public void run() { 

     try { 
      Thread.sleep(1000); 
      System.out.println(Thread.currentThread().getName()); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

} 

它只顯示這個輸出。 主要 線程0 主要 或本 線程0 主要

從這個結果我明白線程之後完成它的運行方式。正在運行的線程進入死態,並調用Thread obj方法不工作,但我無法理解背後的原因,因爲Thread對象是技能參考,Thread類的其他方法又如何。 like yield()? start()?

這裏是另一種情形了清晰的認識我的話

public class Main { 

    public static void main(String[] args) throws ParseException { 
     Student s = new Student(); 

     Thread t = new Thread(s); 

     t.start(); 

     if (!t.isAlive()) { 

      t.start(); 
     } 

    } 
} 

class Student implements Runnable { 
    public void run() { 

     try { 
      Thread.sleep(1000); 
      System.out.println(Thread.currentThread().getName()); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

} 

文件說,如果我們調用start方法對線程t對象,然後它會拋出java.lang.IllegalThreadStateException。但上面的代碼工作正常。 我很困惑Thread類的哪些方法依賴於運行線程和線程對象。我希望你能理解這個問題。 在此先感謝?

回答

2

t.start()啓動線程後右,這種情況:

if (!t.isAlive()) 

是veeeeeeeeeeeeeeeeeeery不可能實現 - 因爲開始線程不會阻塞。這就是爲什麼它只是跳過(因爲t.isAlive() == true),並進一步沒有例外。

+0

我知道大部分時間它不會發生,但爲什麼運行和其他方法仍然不起作用我的第一個代碼 –

+0

,因爲't'已經在第一次調用't'時使用了'Runnable s' 。開始()'。 –

+0

「如果此線程是使用單獨的Runnable運行對象構造的,那麼將調用該Runnable對象的運行方法; *否則,此方法不執行任何操作並返回。*」--https://docs.oracle.com/javase/7 /docs/api/java/lang/Thread.html#run%28%29 –

2

你可以在兩個方面做到這一點。這幾乎是一樣的。你應該開始在你的第一個代碼文件中的線程只是一個簡單的

t.start(); 

我會從你上面的代碼刪除所有t.run(),因爲您要建立與實施內部類新Thread對象。

+0

'run'方法不啓動線程。 – CKing

+0

實現內部類的第一件事學生類是獨立的類。其次,我多次調用run方法來知道爲什麼這個方法沒有被調用,因爲它只是簡單的對象駐留在堆上,它仍然指向並且反對場景故事背後的原因。 –

+0

但是這個代碼看起來很無用。 – Norukh

2

在你的第一次嘗試,你永遠不會重新啓動線程:

t.start(); 
t.run();// does not restarts the thread, it simply makes synchronous call the run(), hence you don't get the exception 
t.start();// add this line, to restart the thread and get the exception 

在第二次嘗試,因爲線程可能開始又活的,按你的條件線程不能活着,它的條件失敗無法重新啓動線程。

t.start(); 
t.join();// add this line, it allows thread to complete first 
if (!t.isAlive()) { 
    t.start(); 
} 

P.S.

爲了啓動一個線程撥打電話start(),這將導致異步呼叫run()。如果你打電話給run(),它不會以線程啓動,它會像普通方法調用一樣進行同步調用。

+0

好的Arvind我明白了,但我不明白爲什麼會發生。因爲我運行它擴展Thread類我開始調用run方法很多時間和它的工作原理。 –

+0

@Arvind你不能在同一個'Thread'上兩次調用'start()'。 – artaxerxe

+0

@artaxerxe,請仔細閱讀OP文章,OP問爲什麼沒有運行時錯誤? – Arvind

1

在您提供的第一個例子,程序不顯示等於你t.start() + t.run()調用線程名稱的計數的原因是,後一個線程是死了,你不能在它start()run()再打電話。它已經死了。有3個輸出的原因可能是因爲直到t.start()進入死狀態,其他2個調用才能執行。

在第二個示例中,您應該知道,調用start()時,線程狀態將處於活動狀態。無論如何,在併發環境中,如果不涉及​​,則無法依賴操作調用順序,但從得到的結果來看,似乎t.start()在調用t.isAlive()之前被調用。 希望能提供幫助。

+0

如果我從線程類延伸到線程已死亡後,如何處理。它的運行方法正在工作 –

+0

@ T.Malik您無法從對象中擴展。你從一個班級延伸。請更確切地說,如果我不明白的話。 – artaxerxe

+0

嗯好吧,我明白了。謝謝 –

0

我在一本書中讀到Thread對象和Running Thread是不一樣的東西。

對,「線程」是您的代碼的執行。 A Thread是一個Java對象,可用於創建和管理「線程」的生命週期。直到調用Thread對象的.start()方法,並且Thread對象即使在「線程」完成其工作並消失後仍然可以繼續存在,「線程」纔會創建。