0

ThreadPoolExecutor を使用して別のスレッドで DNS クエリを実行するすべてのルーチンを呼び出すことにより、非同期 DNS リゾルバーを実装しようとしています。

Callable オブジェクトを次のように定義します。

public class SocketAddressCreator extends DnsCallable<String, InetSocketAddress> {
    private static final Logger log = Logger.getLogger(SocketAddressCreator.class);

    private int port;
    public SocketAddressCreator(String host, int port) {
        super(host);
        this.port = port;
    }
    public InetSocketAddress call() throws Exception {
        log.info("Starting to resolve. Host is: " + target + " .Port is: " + port);
        long start = System.currentTimeMillis();

        **InetSocketAddress addr = new InetSocketAddress(target, port);**

        log.info("Time waiting: " + (System.currentTimeMillis() - start));

        return addr;
    }
}

基本的に、呼び出し可能オブジェクトはホスト名を InetAddress に解決しようとします。

次に、ExecutorService を定義します。

executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
                    public Thread newThread(Runnable r) {
                        Thread t = Executors.defaultThreadFactory()
                                .newThread(r);
                        t.setName("DnsResolver");
                        t.setDaemon(true);
                        return t;
                    }
                });

Callable タスクを送信します。

    ..............
    **Future<V> f = executor.submit(task);**

    try {
        log.info("Query will be made");
        log.info("Queue size: " + executor.getQueue().size());
        **result = f.get(timeout, TimeUnit.MILLISECONDS);**
        log.info("Queue size: " + executor.getQueue().size());
        log.info("Query is finished");
    } catch (TimeoutException e) {
        boolean isCancelled = f.cancel(true);
        log.info("Task was cancelled: " + isCancelled);
        log.info("Queue size: " + executor.getQueue().size());
        ..........
    }
    ..............

次に、プログラムによってスローされたログを確認しましたが、それらは非常に奇妙です。これは、DNS の解決にタイムアウトがある場所です。

DnsResolver : Queue size: 1
DnsResolver : Task was cancelled: true
DnsResolver : Queue size: 1

Callable オブジェクトを送信した後、future.get(long, TimeUnit) を呼び出す前のキュー サイズは 1 です。しかし、それで問題ありません。ただし、TimeoutException をキャッチして Future をキャンセルすると、キューのサイズは同じ (1 つ) になります。私のプログラムには、Callable タスクを ExecutorService に送信するスレッドが 1 つだけあり、同じスレッドが結果も取得します。それ以上に、さらに奇妙な問題があります: Callable.call() メソッドが呼び出されないのは、呼び出された場合にログ メッセージが表示されるからです。

log.info("Starting to resolve. Host is: " + target + " .Port is: " + port);

Callable が呼び出されていないときに、 future.get(long, TimeUnit) メソッドが TimeoutException をスローする可能性があるのはなぜでしょうか?

4

1 に答える 1