2015-05-07 122 views
1

我正在做一些實驗來嘗試和理解線程在實踐中。請看下面的代碼片段:這是一個main函數產生一個線程監聽端口2020此線程,反過來,偵聽此端口,並在任何一個客戶端連接上的連接,它產生另一個線程睡一點點然後寫入套接字。Scala中有趣的線程行爲

class MyRunner(s:Socket,num:Int) extends Runnable{ 

    val r = scala.util.Random 

    def run(): Unit ={ 

    if(num == 5) 
     Thread.sleep(15000) 
    else 
     Thread.sleep(1000) 

    s.getOutputStream.write(s"My number is ${num}! \n".getBytes) 
    s.getOutputStream.close() 
    } 
} 

// this thread opens a MyRunner thread on each new connection 
class MyService extends Runnable{ 

    val serverSocket = new ServerSocket(2020) 

    var num = 0 

    def run():Unit = { 
    while(true){ 
     val socket = serverSocket.accept() 
     num += 1 
     (new MyRunner(socket,num)).run() 
    } 
    } 
} 

// main function 
object app { 
    def main(args: Array[String]) { 
    (new MyService).run 
    } 
} 

現在我正在測試此設置。這是我做的:我開了兩個終端窗口,並在他們每個人我輸入命令:在終端的一個

$ for i in `seq 1 5`; do netcat localhost 2020; done 

事情是,當達到數5時(根據條件),其他一個不會繼續運行。兩個客戶端都會停止,直到15秒超時完成。

我想知道我在做什麼錯的,因爲我想用線程的整個目的是讓非阻塞的應用程序,可以服務的客戶,即使對方是忙。

P.S:我在VirtualBox的VM具有4個可用的處理器(從總8在我的主機)上運行此。

回答

7

您的應用不會創建任何線程。創建一個線程是這樣的:

Thread serverThread = new Thread(new MyService()); 
serverThread.start(); 

thread.start()方法是由圖書館提供的代碼時,你要創建一個新的線程調用低級別的方法。

serverThread.run()方法是代碼提供了調用新線程的方法。


加分:學習如何使用線程池(例如,java.util.concurrent.ThreadPoolExecutor),而不是創建和銷燬一個新的線程爲每個客戶端連接。創建和銷燬線程很昂貴。

+0

是的。我知道我誤解了一些東西。謝謝。 –

+0

您是否有任何有關ThreadPoolExcecutor的信息? – Shondeslitch

+2

@Shondeslitch,標準Java教程中的「併發」一章可能是一個很好的開始:https://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html –