2011-02-11 86 views
0

好的,這是我的問題。java單線程安全

我需要創建一個套接字程序,可以處理來自我的客戶端應用程序的多個連接(讓我們稱它爲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); 
    } 
} 

做我做到了對?或者單身人士不可能做到這一點?

感謝您的幫助。

+0

您能否解釋爲什麼所有打開的連接必須始終只打印到最新的流? – 2011-02-11 04:44:42

+0

你想要一張海報來解釋他們的要求嗎?這不是有點傻嗎?這不像他在問一個技術上不可行的問題。 – 2011-02-11 04:49:40

回答

3

不幸的是,這不是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 Singleton Pattern

您還需要通過使用​​,Lock,或者原子操作,可以讓訪問辛格爾頓的狀態線程安全(AtomicIntegerAtomicReference,等..)作爲necessa RY。