java java单例线程安全
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4965534/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java singleton thread safe
提问by Willy
Ok, here is my problem.
好的,这是我的问题。
I need to create a socket program that can handle multiple connection from my client apps (lets call it apps1). I handle this using thread (so each connection was thrown into a new thread)
我需要创建一个套接字程序,它可以处理来自我的客户端应用程序的多个连接(我们称之为 apps1)。我使用线程处理这个(所以每个连接都被扔到一个新线程中)
The problem is I can accept request from all open connection but when I want to send a response , I must send it through the latest connection only. So if I have 3 connections (con1,con2,con3) I can accept request from con1, con2 and con3 but I must send the response through con3 (assuming con3 is the latest connection)
问题是我可以接受来自所有打开的连接的请求,但是当我想发送响应时,我必须只通过最新的连接发送它。因此,如果我有 3 个连接(con1、con2、con3),我可以接受来自 con1、con2 和 con3 的请求,但我必须通过 con3 发送响应(假设 con3 是最新的连接)
I thought of using a singleton, with a PrintWriter parameter. So everytime there is a new connection ,they call the singleton and update the parameter and when I want to send the response, I get the PrintWriter first before sending.
我想过使用带有 PrintWriter 参数的单例。因此,每次有新连接时,他们都会调用单例并更新参数,当我想发送响应时,我会在发送之前先获取 PrintWriter。
Here is my Singleton class :
这是我的单例类:
public class Singleton {
private static final Singleton instance = new Singleton();
PrintWriter out;
public static Singleton getInstance() {
return instance;
}
public Singleton ()
{
if (instance != null) {
throw new IllegalStateException("Already instantiated");
}
}
public PrintWriter getPrintWriter ()
{
return this.out;
}
public void updatePrintWriter (PrintWriter out){
this.out = out;
}
}
This is my main program :
这是我的主要程序:
public class SocketAccept{
private ServerSocket mainSocket;
private Socket clientSocket;
public SocketAccept (int portNumber) {
Singleton s = Singleton.getInstance();
do {
try {
mainSocket = new ServerSocket(portNumber);
clientSocket = mainSocket.accept();
s.updatePrintWriter(new PrintWriter(clientSocket.getOutputStream(), true));
ClientThread (clientSocket);
} catch (IOException ex) {
Logger.getLogger(TestClass.class.getName()).log(Level.SEVERE, null, ex);
}
}while (true);//need to change this into thread pool or connection pool
}
}
and this is my thread that handle socket :
这是我处理套接字的线程:
public class ClientThread extends Thread {
private Socket cs;
Singleton s = Singleton.getInstance();
PrintWriter out;
private String read(Socket sc) {
String request = "";
//read request here
return request;
}
private String process(String request) {
String response = "";
//process request here
return response;
}
public ClientThread(Socket clientSocket) {
this.cs = clientSocket;
}
@Override
public void run() {
String requestMsg = "";
String responseMsg = "";
do {
requestMsg = read(cs);// read the message
if (requestMsg.equalsIgnoreCase("SHUTDOWN")) {
break;
}
responseMsg = process(requestMsg);
out = s.getPrintWriter();
out.write(responseMsg);
} while (true);
}
}
Do I did it right? Or it is impossible to do it with singleton?
我做对了吗?或者用单例是不可能做到的?
Thanks for the help.
谢谢您的帮助。
回答by Tim Bender
Unfortunately, that is not a thread safe implementation of the Singleton pattern. I don't think you need one in this case either, an AtomicReferencewill probably work just fine. Try this:
不幸的是,这不是单例模式的线程安全实现。我认为在这种情况下您也不需要一个,AtomicReference可能会正常工作。试试这个:
public class SocketAccept{
private ServerSocket mainSocket;
private Socket clientSocket;
private final AtomicReference<PrintWriter> printWriterHolder = new AtomicReference(null);
public SocketAccept (int portNumber) {
Singleton s = Singleton.getInstance();
do {
try {
mainSocket = new ServerSocket(portNumber);
clientSocket = mainSocket.accept();
printWriterHolder.set(new PrintWriter(clientSocket.getOutputStream(), true));
Thread clientThread = new ClientThread (clientSocket, printWriterHolder);
clientThread.start();
} catch (IOException ex) {
Logger.getLogger(TestClass.class.getName()).log(Level.SEVERE, null, ex);
}
}while (true);//need to change this into thread pool or connection pool
}
}
...
...
public class ClientThread extends Thread
...
private final AtomicReference<PrintWriter> printWriterHolder;
public ClientThread(Socket clientSocket, AtomicReference<PrintWriter> holder) {
this.cs = clientSocket;
this.printWriterHolder = holder;
}
@Override
public void run() {
String requestMsg = "";
String responseMsg = "";
do {
requestMsg = read(cs);// read the message
if (requestMsg.equalsIgnoreCase("SHUTDOWN")) {
break;
}
responseMsg = process(requestMsg);
out = printWriterHolder.get();
out.write(responseMsg);
} while (true);
}
}
If you really do want to use the Singleton pattern, here is a reference from SO where the question has a good thread-safe implementation for creating the Singleton: Java Singleton Pattern
如果你真的想使用单例模式,这里是来自 SO 的参考,其中问题有一个很好的线程安全实现来创建单例:Java Singleton Pattern
You will also need to make accessing the Singleton's state thread-safe by using synchronized
, Lock
, or atomic operations (AtomicInteger
, AtomicReference
, etc..) as necessary.
你也将需要通过访问辛格尔顿的状态线程安全的synchronized
,Lock
或者原子操作(AtomicInteger
,AtomicReference
,等)是必要的。