当你google for 多线程java服务器时,大多数时候你会得到一个基于以下模式的解决方案:
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 Concurrency in Practice 中提供的安全发布习语有什么关系?
安全地发布对象,两者都是 引用对象和 必须使对象的状态可见 其他线程同时。一个 正确构造的对象可以 安全发布者:
- 从中初始化对象引用 一个静态初始化器。
- 存储a 将它引入一个易变的领域。
- 将参考文献存入决赛 领域。
- 存储对它的引用 一个受到适当保护的领域 (同步)锁。
在没有任何额外同步的情况下在socket
方法中使用run()
是否真的安全,它是否安全发布?请不要只写是或否。
答案 0 :(得分:2)
是的,这是安全的,因为线程的开始定义了一个发生之前的关系。也就是说,MultiThreadServer
构造函数调用在执行线程的run
方法之前发生。
来自Java Language Specification 17.4.4-17.4.5:
在启动线程
中的任何操作之前,对线程的start()调用发生
实践中的Java并发中的注意事项适用于其他现有线程可以访问对象的情况,因此它们不适用于这种情况。