1

サーバーがクライアントからメッセージを受信/送信する継続的なスレッドを作成しようとしていますが、次の要素をチェックしようとするとスタックします:

public void run()
{
    try
    {
        try
        {
            ArrayList<Socket> connections = parent.getConnections();
            in = new Scanner(socket.getInputStream());

            while(true)
            {
                if(in.hasNextLine()) // Gets stuck here
                {
                    String message = in.nextLine();
                    System.out.println("Client said " + message);
                }
            }
        }

        finally
        {
            socket.close();
        }
    }

    catch(Exception e)
    {
        e.printStackTrace();
    }

指定したポイントでループがスタックしないようにするにはどうすればよいですか

4

1 に答える 1

1

「行」を処理できるようにしたいと仮定すると、おそらく次のようなものから始めます。

public class SocketReader implements Runnable {

    private final InputStream stream;
    private final Queue<String> destination;
    private volatile boolean active = true;

    private SocketReader(InputStream stream, Queue<String> destination) {
        this.stream = stream;
        this.destination = destination;
    }

    public static SocketReader getReader(Socket toRead, Queue<String> destination) throws IOException {
        return new SocketReader(toRead.getInputStream(), destination);
    }

    public void shutdown() {
        active = false;
    }

    public void run() {
        while(active) {
            if (stream.hasNextLine() && active) {
                final String line = stream.nextLine;
                destination.add(line);
            }
        }
        try {
            stream.close();
        } catch (IOException e) {
            // Log somewhere
        }
    }
}

これを独自のスレッドに (または実際にはスレッドまたはエグゼキューター プールの一部として) ドロップすると、アプリケーションの残りの部分がこのコードに関して非ブロックになります。 からの更新を待っている間、これがブロックされることを期待stream.hasNextLine()してください。BlockingQueue積極的にキューをポーリングしたくないが、他の方法で更新を処理している場合は、 を指定することもできます。

次に、出力のために次のようなことを行うことができます。

public class QueuedPrinter implements Runnable {

    private final Queue<String> input;
    private final PrintStream destination;
    private volatile boolean active;

    public QueuedPrinter(Queue<String> input, PrintStream destination) {
        this.input = input;
        this.destination = destination;
    }

    public void shutdown() {
        active = false;
    }

    public void run() {
        while(active) {
            final String line = input.poll();
            if (line != null && active) {
                destination.println(line);
            }
        }
    }

}

私はこれをテストしていないことに注意してください。他の Checked 例外については、少し調整する必要があるかもしれません。おそらく追加のエラー チェック コードを追加する必要があります (null 処理が頭に浮かびます)。また、これは完全にスレッドセーフではありませんが、ほとんどの用途には「十分」である可能性があります。

于 2012-06-05T16:28:53.237 に答える