单身的java线程安全(java singleton thread safe)

2019-11-04 16:48发布

好吧,这里是我的问题。

我需要创建一个套接字程序可以处理从我的客户端应用程序的多个连接(可以称之为APPS 1)。 我处理这个使用线程(因此每个连接都扔进一个新的线程)

问题是,我可以从所有打开的连接请求,接受,但是当我要发送的响应,我必须只通过最新的连接发送。 所以,如果我有3个连接(CON1,CON2,CON3)我可以接受来自CON1,CON2和CON3请求,但我必须把通过CON3响应(假设CON3是最新的连接)

我想用一个单独的,使用PrintWriter参数。 所以每次有新的连接,他们称之为单和更新参数,当我想发送的响应,我在发送之前先拿到的PrintWriter。

这里是我的Singleton类:

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

这是我的主要程序:

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

这是我的线程处理插座:

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

难道我这样做是正确的? 或者,它是不可能与单做呢?

谢谢您的帮助。

Answer 1:

不幸的是,这不是一个线程安全的实现Singleton模式。 我不认为你需要在这种情况下一支,一个的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);
    }
}

如果你确实想使用Singleton模式,这里是从SO参考其中的问题有创建辛格尔顿良好的线程安全的实现: Java的单例模式

您还需要使访问辛格尔顿的状态线程安全的,通过使用synchronizedLock ,或原子操作( AtomicIntegerAtomicReference必要,等..)。



文章来源: java singleton thread safe