2012-01-13 20 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

IMHO、これを行わないでください。建設中にthisの参照がエスケープできるようにしています。

+0

説明できますか? – Mazzy

+0

@Mazzy、あなたは、別のオブジェクトが部分的に構築されたオブジェクトを見ることを許可しています。 – mre

+1

静的ファクトリメソッドを使用して、負の副作用なしに目的の効果を達成できます。 – emory

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 
} 
} 

サーバーの参照も例外が発生していないにもかかわらず、nullの場合もあります。これは、スレッドが作成された実行可能ファイルを使用し、クラスのコンストラクタが終了していなくてもrunメソッドを呼び出すためです。

1

カップルコンストラクタからThread.start()を分割するために、より良いな理由:

  1. あなたは今まで、このようなjava.utilのようスレッドを実行するためにいくつかの他のフレームワーク/システムを使用したい場合。あなたはそうするかもしれない。
  2. スレッドを中断したい場合は、そのスレッドへの参照が必要です。別のコード行でスレッドを作成すると、これはやや日常的な/慣用的なものになります。例えば

    スレッドrememberMe =新しいスレッド(サーバー).start();

元のコードでは、Serverには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

戻り値Serverを追加する意味は何ですか? – Mazzy

+0

作成したサーバーへの参照が必要な場合は必要です。サーバーを作成して起動するだけであれば、それは必要ありません。 – emory

+0

@emory、+1これは 'newInstance'アプローチに似ています。 – mre

関連する問題