在里面调用新线程是构造函数

时间:2012-01-13 18:14:15

标签: java multithreading

创建一个线程并在类的构造函数中调用它的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() {
    }
}

5 个答案:

答案 0 :(得分:11)

恕我直言,不要这样做。您允许this引用在构造期间转义。

答案 1 :(得分: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。这是因为即使你的类的构造函数还没有完成,Thread也会使用创建的runnable并调用run方法。

答案 2 :(得分:1)

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

更容易测试。它允许您创建一个Server实例并对其方法进行单元测试,而不会产生一个线程。

答案 3 :(得分:1)

将Thread.start()与构造函数分开的几个更好的理由:

  1. 如果您想使用其他框架/系统来运行线程,例如java.util.concurrent.Executor,您可以这样做。
  2. 如果您想要中断线程,则需要引用它。在单独的代码行中创建线程使得这更常规/惯用。 e.g。

    线程rememberMe =新线程(服务器).start();

  3. 在原始代码中,服务器可以有一个字段来记住myThread,但它没有。

答案 4 :(得分: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(){
}
}