著作一覧 |
HTTPクライアントの簡単な実装をすることを想定。
Javaで記述することを前提。
で、最初、何も考えなければURLクラスを使うことになる。
でも、3秒たっても返事がなければあきらめたいと考えたとする。
方法1:
クライアント処理をスレッドで実行し、3秒間のwaitをかけ、3秒後に戻ってきたらタイムアウト。そうじゃなければOK。この場合、スレッド側では結果をどこかに置いておいてからnotifyする。
が、この実装がダメなのは10000回くらい短時間のうちに複数のスレッドが送信処理をするとすると、すごい勢いでスレッドがぽんすかぽんすか作られることだ。
というわけで、そんなことはしないで、
方法2:
モニター専用スレッド(シングルトン)を用意しておき、元のスレッドはコネクションの生成前にこのスレッドの監視テーブルに自分を登録しておいてからおもむろに送受信を開始。終了時に登録解除。モニター専用スレッドは100ミリ間隔くらいで登録テーブルをチェックしエクスパイアしているスレッドを叩き起こす。
とすることを考えてみる。が、それなりに難しい。というのは、叩き起こすと一口に言っても実際にはThread#interruptしか手が無いように見えるからだ。HttpUrlConnection#disconnectでも良いかも知れない?(実装依存に見える)微妙なタイミングの問題があるはずだから、interruptedを呼び出してステートをクリアする必要もありそうだとか、HttpUrlConnectionがSelectorを利用しているかどうかも実装依存だとかいろいろ。
というわけで、やっぱり方法1にしてみたり。
もし、送信先がひとつならシングルトンのコネクションを作ってパイプライニングするほうが賢いかも。しかし、それも難しいだろう。
結局、安全性と確実性を両立させるにはNIOを直接利用するのが良さそうだということになってしまう。それも面倒だ(というか、それならむしろJNIを使うことを前提してCで書いたほうが良いようにも思える)。面倒だと感じるとバグが入るので、やめておくべきだろう。
んがんぐ
Ruby is hot, Java is cool, C# is neither。
simplifing it:
Java 1 = Oak = Objective-C + Ada + C++ + Cedar + Smalltalk + Scheme
Ruby = Python + CLU + Eiffel + SmallTalk + Perl
C# 1.0 = C++ + Java + Delphi + VB
C# 2.0 = C# 1.0 + Ruby
Java 2 (v1.5.0) = C# 2.0 + Java 2 (v1.4.2.03)
Has any one seen C Omega...the descendant of C# 2.0?
If ruby is hot then C# is hot, java is cool c# is cool, c# is cool and hot so java is cool and hot too...the circle of languajes is complete. Both worlds are cool and hot =) No fighting...
rubyがホットならC#もホットで、javaがクールならC#もクールで、まあどっちでもいいじゃん。
ジェズイットを見習え |
20世紀にJavaスレッドを触ったきりなのでまちがってるかもしれませんが、スレッドに話しかけるのは難しいですよね。Rubyのスレッドはらくちんすぎ。ネイティブスレッドになってもいまのらくちんさを保ってほしいぞぞ>Ruby。
確かにそうですね。というか、両方あるほうが良いんだけどな、と最近良く思います。<br>#ソケットのcloseがすごく難しいというのもあるけど。APIとしてのclose後にも遷移があるし、なんでもRSTとも行かないし。
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/net/URLConnection.html#setReadTimeout(3000)<br>か<br>System.setProperty("sun.net.client.defaultReadTimeout", "3000");<br><br>でできるらしい。情報源↓<br>http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=19287&forum=12
修正<br>http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/net/URLConnection.html#setReadTimeout(int)
どうもありがとうございます。<br>残念なことに実装は1.5からなんですよね……。<br>システムプロパティは、以前調べた時はグローバルに影響した(つまり、5秒と10秒といった複数のタイムアウトを利用したい場合に使えない=クライアントAPL専用、サーバー用だと接続先も多岐に渡るし、複数のスレッドから同時に行くかも知れないので動的な設定もできないし、かつ最初に読み込んだ値をキャッシュしていた)ので、これも残念なことに使えないのです。