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 をスローする可能性があるのはなぜでしょうか?