簡體   English   中英

Java單例線程安全

[英]java singleton thread safe

好的,這是我的問題。

我需要創建一個套接字程序,該程序可以處理來自客戶端應用程序的多個連接(我們稱其為apps1)。 我使用線程處理此問題(因此每個連接都被拋出一個新線程)

問題是我可以接受所有打開的連接的請求,但是當我要發送響應時,我只能通過最新的連接發送它。 因此,如果我有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);
    }
}

我做對了嗎? 還是單身不可能做到這一點?

謝謝您的幫助。

不幸的是,這不是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的參考,其中該問題對於創建Singleton具有良好的線程安全實現: Java Singleton Pattern

您還需要根據需要通過使用synchronizedLock或原子操作( AtomicIntegerAtomicReference等)來使訪問Singleton的狀態線程安全。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM