5

4 台のマシンに接続し、ソケットからデータを読み取る必要があります。nio2 の非同期モデルを使用することにしました。

ここに疑似コードがあります:

class Connector {

    private final AsynchronousChannelGroup group;
    private final String host;
    private final int port
    //...
    
    public void connect() {
        try (AsynchronousSocketChannel client = AsynchronousSocketChannel.open(group)) {

            client.connect(new InetSocketAddress(host(), port())).get(5, TimeUnit.SECONDS);

            if (!group.isShutdown()) {
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                client.read(buffer, 5, TimeUnit.SECONDS, new Attachement(buffer), new ReadHandler(client)); //#1
            }

        } catch (Exception e) {
            //
        }
    }

    private class ReadHandler implements CompletionHandler<Integer, Attachement> {

        final AsynchronousSocketChannel channel;

        @Override
        public void completed(Integer result, Attachement attachment) {
            attachment.buffer.clear();
            channel.read(attachment.buffer, 5, TimeUnit.SECONDS, attachment, this);
        }

        @Override
        public void failed(Throwable exc, Attachement attachment) {
            closeChannel();
        }

        void closeChannel() {
            try {
                if (channel.isOpen()) {
                    channel.close();
                }
            } catch (IOException e) {
                // do something else
            }
        }
    }
}

このコードを実行するには、新しいグループを作成し、それをすべてのConnectorsに渡します。

ExecutorService executor = Executors.newFixedThreadPool(4);
AsynchronousChannelGroup group = AsynchronousChannelGroup.withThreadPool(executor);

//for each server
Connector connectorX = new Connector(group, serverX.host, serverX.port);

問題:

スレッドは、最初の読み取り (//#1コメントがある場所) の後に解放されます。

解決 !

これを修正するCountDownLatchために、スレッドが読み取りを待機するように を導入しました。


//...
private CountDownLatch latch; 

public void connect() {

        latch = new CountDownLatch(1);

        try (AsynchronousSocketChannel client = AsynchronousSocketChannel.open(group)) {

            client.connect(new InetSocketAddress(host(), port())).get(5, TimeUnit.SECONDS);

            if (!group.isShutdown()) {
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                client.read(buffer, 5, TimeUnit.SECONDS, new Attachement(buffer), new ReadHandler(client)); //#1
            }
            
            latch.await();

        } catch (Exception e) {
            //...
            latch.countDown();
        }
}

質問:

これは ( CountDownLatch) 問題を解決する正しい方法ですか? いいえの場合、最善の方法は何ですか?

スレッドのブロック ( latch.await()) は、非同期モデルと矛盾していませんか?

4

0 に答える 0