Java单例线程安全 [英] java singleton thread safe

查看:58
本文介绍了Java单例线程安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,这是我的问题.

Ok, here is my problem.

我需要创建一个套接字程序,该程序可以处理来自客户端应用程序的多个连接(我们称其为apps1).我使用线程处理此问题(因此每个连接都被抛出一个新线程)

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)

问题是我可以接受来自所有打开的连接的请求,但是当我要发送响应时,我只能通过最新的连接发送它.因此,如果我有3个连接(con1,con2,con3),我可以接受来自con1,con2和con3的请求,但是我必须通过con3发送响应(假设con3是最新的连接)

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)

我想到了使用带有PrintWriter参数的单例.因此,每当有一个新的连接时,它们都会调用单例并更新参数,并且当我要发送响应时,在发送之前我首先要获得PrintWriter.

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.

这是我的Singleton课堂:

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

这是我的主程序:

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?

感谢您的帮助.

推荐答案

不幸的是,这不是Singleton模式的线程安全实现.在这种情况下,我也不认为您需要一个 AtomicReference 可能会正常工作.试试这个:

Unfortunately, that is not a thread safe implementation of the Singleton pattern. I don't think you need one in this case either, an AtomicReference will probably work just fine. Try this:

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那里获得参考,该问题对于创建Singleton具有良好的线程安全实现:

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

您还需要根据需要使用synchronizedLock或原子操作(AtomicIntegerAtomicReference等)来访问Singleton的状态线程安全.

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.

这篇关于Java单例线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆