2011-02-11 8 views
0

これは私の問題です。java singleton thread safe

クライアントアプリケーションから複数の接続を処理できるソケットプログラムを作成する必要があります(apps1と呼ぶことができます)。

問題は開いているすべての接続から要求を受け入れることができますが、応答を送信するときは、最新の接続のみで送信する必要があります。 con3、con2、con3の3つの接続(con1、con2、con3)を受け入れることができますが、con3(con3が最新の接続であると仮定)を使って応答を送信する必要があります。

私は、 PrintWriterパラメータを使用します。したがって、新しい接続があるたびに、シングルトンを呼び出してパラメータを更新し、レスポンスを送信するときは、送信前にPrintWriterを先に取得します。ここで

は私のシングルトンクラスである:

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

開いているすべての接続を常に最新のストリームにのみ印刷する必要がある理由を説明してください。 –

+0

ポスターを自分の要件について説明したいですか?それはちょっとばかげていませんか?まるで彼が技術的に実現不可能な質問をしているのではない。 –

+0

@ Scrum Meisterもし私ができるなら、私は通常理由を知っていれば理由を知ることがあるので、理由を説明します。悲しいことにクライアントはそれを何の説明もせずに求めます。 – Willy

答えて

3

残念ながら、これはシングルトンパターンのスレッドセーフ実装ではありません。私はあなたがこの場合にもどちらかを必要とは思わない、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); 
    } 
} 

あなたが本当にシングルトンパターンを使用したいならばが、ここで問題は、作成するための良いスレッドセーフな実装を持っているSOからの参照ですシングルトンは:Java Singleton Pattern

またnecessaとして(.. AtomicIntegerAtomicReference、など)​​、Lock、またはアトミック操作を使用してシングルトンの状態スレッドがセーフアクセスするようにする必要がありますry。

+0

うわー、 AtomicReferenceを使用した「シンプルな」ソリューションです(これについては私が最初に読んでいます)。どうもありがとうございました – Willy