2010-10-03 54 views
1

当谷歌多线程Java服务器,大部分的时间你会得到基于下面的模式解决方案:多线程Java服务器VS安全出版物

public class MultiThreadServer implements Runnable { 
    private Socket socket; 

    MultiThreadServer(Socket socket) { 
    this.socket = socket; 
    } 

    public static void main(String args[]) throws Exception { 
    ServerSocket serverSocket = new ServerSocket(4444); 
    while (true) { 
     new Thread(new MultiThreadServer(serverSocket.accept())).start(); 
    } 
    } 

    public void run() { 
    // ... 
    PrintWriter out = new PrintWriter(socket.getOutputStream(), true); 
    BufferedReader in = new BufferedReader(
       new InputStreamReader(
       socket.getInputStream())); 
    // ... 
    } 
} 

那如何关联到安全的出版物习语Java并发实践

要安全地发布对象,无论是 参考对象和 对象的状态必须在同一时间内看到其他 线程。甲 正确构造的对象可以是 安全的出版商:

  • 初始化从 静态初始化一个对象引用。
  • 将 的引用存储到易失性字段中。
  • 将参考存储到最终的 字段中。
  • 将对其的引用存储到 由 (同步)锁适当保护的字段。

是不是真的安全run()方法中使用socket没有任何额外的同步,是它安全地发布?请不要只写

回答

2

是的,这是安全的,因为线程的开始定义了发生在之间的关系。也就是MultiThreadServer的构造函数调用发生在执行之前的线程的run方法。

Java Language Specification 17.4.4-17.4.5:

调用开始()上线之前发生在启动线程的任何行动从Java并发

注意事项实践适用于当其他现有线程可访问对象的情况下,因此它们不适用于此情况。

+0

有道理,谢谢! – lukem00 2010-10-03 22:49:05

+0

这意味着如果线程是从线程池中取出的,而不是新的线程(),那么它不会安全 - 或者我没有正确地得到它? (在这种情况下,将'socket'字段标记为final是否足够?) – nos 2010-10-04 16:19:31

+0

@nos:'ExecutorService'在javadoc中显式地提供了相同的保证:http://download.oracle.com/javase/6/docs/api/的java/util的/并行/ ExecutorService.html – axtavt 2010-10-04 16:25:48