2012-01-13 41 views
6

創建一個線程並在類的構造函數中調用其start()方法是否正確?調用內部的新線程是構造函數

public class Server implements Runnable { 

    private ServerSocket server; 

    public Server(int port) { 
     try { 
      //Opens a new server 
      server = new ServerSocket(port); 
     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 

     new Thread(this, "Server").start(); 
    } 

    @Override 
    public void run() { 
    } 
} 

回答

11

恕我直言,不要這樣做。在建設過程中,您允許參考this

+0

你能解釋一下嗎? – Mazzy 2012-01-13 18:20:03

+0

@Mazzy,您允許另一個對象查看部分構造的對象,這可能會產生嚴重的負面影響。 – mre 2012-01-13 18:20:34

+1

您可以使用靜態工廠方法來獲得所需的效果,而不會產生負面影響。 – emory 2012-01-13 18:41:24

1
Server s = new Server(); 
Thread t = new Thread(s, "Server").start(); 

更具可測性。它允許你創建一個服務器實例,並單元測試它的方法而不會產生一個線程。

2

當然,你的心不是代碼做這件事,但如果你的代碼是什麼樣子的:

public Server(int port) 
{  
    new Thread(this, "Server").start(); 

    try 
    { 
     //Opens a new server 
     server = new ServerSocket(port); 
    } 
    catch (IOException ioe){ ioe.printStackTrace(); } 

} 
@Override  
public void run(){ 
    if(server == null)throw new NullPointerException();// this may happen 
} 
} 

服務器基準可能是,即使沒有異常發生空。這是因爲線程將使用創建的runnable並調用run方法,即使您的類的構造函數尚未完成。

1

一對夫婦更充足的理由從構造分裂Thread.start():

  1. 如果你想使用一些其他的框架/系統運行的線程,比如java.util中。 concurrent.Executor,你可以這樣做。
  2. 如果您想要中斷該線程,則需要對其進行引用。在單獨的代碼行中創建線程使得這更具有慣例/習慣用法。例如

    線程rememberMe = new Thread(server).start();

在你的原代碼,服務器可能有一個字段記住MyThread的,但事實並非如此。

1
public class Server implements Runnable 
{ 
private ServerSocket server; 

/** 
* Because the constructor is private, the only way to instantiate a Server is through 
* the static factory method. 
* If there are any instantiation problems, the static factory method will fail in 
* first line, before it is put into a thread. 
* It will be put into a thread before being released. 
**/  
public static Server startServer (int port) 
{ 
    Server server = new Server (port) ; 
    new Thread (server , "Server") . start () ; 
    return server ; 
} 

private Server(int port) 
{  
    try 
    { 
     //Opens a new server 
     server = new ServerSocket(port); 
    } 
    catch (IOException ioe){ ioe.printStackTrace(); } 

// don't release me into the wild yet! 
// new Thread(this, "Server").start(); 
} 
@Override  
public void run(){ 
} 
} 
+0

添加價值返回服務器是什麼意思? – Mazzy 2012-01-13 19:14:33

+0

如果您需要對創建的服務器的引用,則這是必要的。如果您只想創建並啓動服務器,則不需要。 – emory 2012-01-13 19:18:53

+0

@emory,+1這與'newInstance'方法類似。 – mre 2012-01-13 20:02:44