2011-02-11 88 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。