乃木坂46(乃木坂って、どこ?、乃木坂工事中)2019-06-23Javaの非同期処理とタイムアウトIT処理に時間がかかるものは非同期で処理するというのはよくある話である。処理に時間がかかるわけなので、何かあったときにほったらかしにしておくのは無責任であるということで、一定時間経過しても処理が終わっていなかったら処理を中断するというタイムアウトを設計したいということがある。これをJavaで書こうとしたらやや面倒なことになった。相談したら「う~んJavaで書くのは難しいねぇ」という反応をされたので、言語として向いていないという説はある。それでもやろうとするならどうすればよいか。■はじめに以下のブログに、書きたいことがほぼ書かれている。nagise.hatenablog.jp特に重要なのは以下の記述である。Threadのrun()中にいるとき、他のThreadからinterrupt()されたとき、実は通常は何も起きない。自動的にInterruptedExceptionが発生して中断してくれるわけではない。InterruptedExceptionが発生して中断してくれるのはThread.sleep()やObject.wait()などの場合に限られる*2。それ以外の場合、プログラムが自分で割りこまれたのかをチェックしてその後の身の振り方を決めなくてはならない。■ThreadとinterruptThread.interrupt()やFuture.calcel()はInterruptedExceptionをthrowするわけではない。interrupted状態にするだけである。何が厄介かというと、この手の話をしているときに8割方サンプルで出てくるThread.sleep()メソッドは、スレッドがinterruptedになったらInterruptedExceptionをthrowする。実際にはThread.sleep()がthrowしているのに、Thread.interrupt()やFuture.calcel()がInterruptedExceptionをthrowしているのだと勘違いされがちである。ググってみると、この勘違いをした情報はワンサカ出てくる。Thread.sleep()ではない何か}すなわち、処理を止めたいときには、タスク側でマメにThread.interrupted()のチェックをする必要がある。■非同期+タイムアウト非同期というのは当然、処理を依頼したらそこで結果が返ってくる。タイムアウト処理というのは一般に、指定された時間だけ待って、終わらなかった場合になんやかんやするという同期的な動きをすることが多い。基本的なタイムアウトの仕方は以下のようなものである。{e.printStackTrace();}Future.get()メソッドで別スレッド処理のタイムアウトを実装できる。これは同期的に待機するので、元々やりたかった非同期処理が実現できていない。TimeUnit.SECONDS);calcelされるtaskでは、既に述べたように、適宜interruptedのチェックで処理中断の制御をする必要がある。いずれにせよ、スレッドプールのクローズ(shutdownメソッドなど)などもする必要があるので、そこまで簡単な実装ではない。(12)月別アーカイブ検索はてなブログをはじめよう!glory_hmさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。