- ベストアンサー
javaのプログラムが止まる
JAVAを使って、ホームページを読み込んでいるのですが、100000ページくらいのURLを読み込んだ辺りでよく止まってしまいます。なぜでしょうか? また、JAVAがURLを読み込んでいる時に、メールチェックをしたり、たくさんのホームページをIEで見ていても止まることが良くあります。 こういったエラー表示の出ないエラーを解決するにはどうしたらよいでしょうか?とても困っています。 教えていただけないでしょうか? 宜しくお願い致します。
- みんなの回答 (26)
- 専門家の回答
質問者が選んだベストアンサー
えーっと、諦めるのが早くないですか? それに、いろいろヒントや解説も書いてありますし、 どこがわからないのかが逆にわかりません。 それと、「時間がないので作って欲しい」という内容に読みとれますが、 丸投げやそれに類似のリクエストには、申し訳ありませんが応えられません。 これは、私の方針というか、気持ちの問題です。 前回、「こちらで追加してもいいのですが」と書いたため、こういう要望になったのだと 思いますが、言い回しの間違いです。 「こちらで追加できなくはないのですが」ということを言いたかったのでした。 すみません。 というわけですので、直接のコードは書きません。 その代り、質問等はわかる範囲でならいくらでもつきあいます。
その他の回答 (25)
- ngsvx
- ベストアンサー率49% (157/315)
>なんのエラー表示もなく、ただ止まるというエラーになっていたようですが、 なぜ、エラーが発生しなかったのでしょうか? エラーではないからです。 止まっているのは、単に待っているだけです。 古いマシンでエラーがでるということですが、どのような内容ですか? それがわからないと、何とも言えません。 >#23のようなコードを自力で思いつくに到るための、参考本ってありますかね? 具体的なものはわかりませんが、少なくても「JAVA言語入門」みたいなタイトルの本では 無いと思います。 だったらどんなタイトルなのかというと、「オブジェクト指向入門」みたいなタイトルの本です。 言語の本というのは概念の表現に重点が置かれています。それに対し「オブジェクト指向入門」は 概念の説明です。 思うに、クラスの概念にたいする理解が足りないのではないかという気がします。 ちなみに、私は「JAVA言語入門」的な本は1冊しか持っていません。 最初にざっと読んで、後は辞書のような使い方をしました。 例えば、「クラスの継承をするときはどう書くんだっけ?」という感じです。 まあ、私の場合JAVAが初めての言語ではないし、オブジェクト指向言語もJAVAが初めて では無かったのですが。
補足
>古いマシンでエラーがでるということですが、どのような内容ですか? たまたまかもしれませんが、今回と同じエラーが頻繁に発生しやすかったです。 本>オブジェクト指向入門ですか。正月を過ぎたころ本格的にやろうと思うのでそのときに調べてみます。参考になるアドバスありがとうございます。 >>プログラムについて 今回、いろいろと、コードを弄っていて分かったのですが、クラスの継承?インターフェイスなどは、ちゃんとした知識をなくして書けるものではないということです。今までは、ちょっと変更して実行すれば、なんとなくしか理解していなくても、コンパイルできて成功していました。しかし、今回はコンパイルすら成功していません。ここに、一応でも、作成したコードを掲載しようかと思ったのですが、長い割りに、相当的外れな答えで、アドバイスを頂いてもそれを理解できるというレベルにない気がするので掲載していません。そのため、暇を見つけて、もっと、本格的にクラスの扱い方などが記載してるテキストを買って勉強しようと思います。しかし、正月を過ぎるまではまともに、時間が取れそうにありません。 正直、今すぐにでもこのプログラムを実行したいのですが、止まるために安定して使えていません。本当に、勝手な理由で申し訳ないのですが、#15補足のコードに実装したものを書いていただけたらもの凄く助かります。何とか、お願いできないでしょうか・・・よろしくお願いいたします。
- ngsvx
- ベストアンサー率49% (157/315)
#15補足のコードへの追加は、ご自分でやってください。 こちらで追加してもいいのですが、理解しないままになってしまいます。 そうすると、以降の改良ができなくなってしまいます。 わからないことは、答えますので、自力で頑張ってください。
補足
現在、#23に書かれた使用例のコードを研究中です。 なんと、なく分かるような、分からないような感じです。現在、いろいろ調べていますが、牛歩のごとくゆっくりと考えていこうと思います。 また、「#15を自力で」に関しては了解いたしました。ご配慮ありがとうございます。私も、自身で理解しながらやっていかないとかなりまずいと痛感しております。 そのために、いろいろ参考になるものも探しているのですが、何か、良いテキストってありますか?オンラインは便利なのですが、目がチカチカして見づらくてつらいです。 一応、私が読んだ本について書いておきます。 一番初めに使ったテキスト「java先生」に関しては、360ページありそれなりに読み応えがありました。 http://www.amazon.co.jp/exec/obidos/ASIN/4839910375/ 同期やインターフェイスについての説明が載っていないというレベルでしたが、ただ、このおかげで、入門者はようやく脱したかなと・・・ 次のテキスト「やさしいJAVA」に関しては、結構読み応えがあって、飛ばしたところも多々あります。 http://www.amazon.co.jp/exec/obidos/ASIN/4797319062 ちなみに、同期やインターフェイスの説明はあるのですが、私の理解力不足も手伝って、もっと、詳しく書いてあってほしいと願うところです。そのため、難しくて仕方なく斜め読み状態です。 また、いろいろな本を読んだり、コードを作ったりしていて、一応は、理解したつもりだったのですが、#23のようなコードの使い方になるなんて、正直、全くの予想外でした。入門レベルは卒業したかなと思っていたのですが、書いていただいたコードが理解できないことを考えると、全然使えるレベルにないなぁと痛感しております。ちなみに、「憂鬱なプログラマのためのオブジェクト指向開発講座」に関しては、とりあえず、このコードを理解するまではお休み中です。 こんな感じですが、今までのレスなどから、同期、インターフェイス、#23のようなコードを自力で思いつくに到るための、参考本ってありますかね? ところで、今回のように、nullを検出できなかったため、なんのエラー表示もなく、ただ止まるというエラーになっていたようですが、なぜ、エラーが発生しなかったのでしょうか?また、今回のエラーのようにエラー表示がなく止まるということって良くあることなのでしょうか?正直、今回のエラー検出は、今でにない苦労をしました。 また、古いPCでも動きをチェックしてみたくて、Thinkpad Celeron 466MHz、Win98Se という昔のパソコンで作業してみました。そうすると、エラーが顕著に現れたためエラーの発見が容易でした。古いパソコンだと、新しいパソコンに比べてかなり厳しくエラーがでるものなのでしょうか? また、ご厚意に甘えて、分からない箇所がありましたら、質問させていただきますので、改めて、よろしくお願いいたします。
- ngsvx
- ベストアンサー率49% (157/315)
コードは、メソッドの中身まで見る必要はありませんよ。 メソッドの説明と、パラメータ、戻り値だけを見ればいいと思います。 もっともそれほど難しいコードではありませんけど。 タイマーに毛が生えたようなものですね。 とりあえず補足をしておきます。 synchronizedはマルチスレッドで動作した場合、同時に実行されないための制御をします。 クラスという観点からしてみれば関係ないので、とりあえず無視すればいいでしょう。 interfaceは、メソッド本体の無いクラスです。C++では多重継承が混乱を招いた教訓から JAVAでは多重継承をできなくした代りにinterfaceというものが作られました。 interfaceというのはJAVAでは当たり前に出てきますから、しっかりとマスターしておかなくては なりません。 interfaceを定義するということは、あるクラス(またはクラスのメソッド)に対して、 役割を定義したり、クラス(またはメソッド)が必要とする機能を定義するということです。 今回の場合は、スレッド監視者が監視の対象とするための条件として、 ・動いているのかを知らせることができる(getTime()) ・「中断しろ」と言われて中断できる(doTimeout()) ことが条件です。 それと、前回のコードでは、ThreadかRunnableであることもキャンセルする条件に加えて いましたが、これは必要ないかもしれません。 次のように直してください。 ●ThreadWatcher.javaの一部 /** * * */ synchronized protected void watchThreads(){ int n = list.size(); for(int i = 0 ; i < n ; i++){ IWatchedThread thread = (IWatchedThread)list.get(i); if(thread.getTime() != -1){ long lastTime = thread.getTime(); long now = new Date().getTime(); if(time < now - lastTime){ thread.doTimeout(); } } } } 次に、簡単な使用例を付けておきます。 ●TestWb.java /* * 作成日: 2004/11/24 * */ package app.webchecker; import java.util.Date; /** * @author ugnag * */ public class TestWb implements IWatchedThread { volatile long lastTime; /** */ public static void main(String args[]){ TestWb test = new TestWb(); ThreadWatcher tw = new ThreadWatcher(); //3秒ごとにチェック tw.setInterval(3000); //4秒停滞していたら、タイムアウト tw.setTime(4000); //監視リストに追加 tw.addWatchedThread(test); //監視の開始 tw.startPatrol(); //処理実行 test.go(); //監視終了 tw.stopPatrol(); } /** */ public void go(){ setLastTime(new Date().getTime()); try{ System.out.println("In"); synchronized(this){ // <-- これが無いと、wait()が実行できない wait(10000);//10秒のウエイト } System.out.println("Out"); }catch(Exception e){ System.out.println("time out"); } System.out.println((new Date().getTime() - lastTime) /1000 + "秒間の実行でした"); setLastTime(-1); } /** */ synchronized public void setLastTime(long time){ lastTime = time; } /** */ synchronized public long getTime(){ return lastTime; } /** */ synchronized public void doTimeout(){ System.out.println("time out 実行"); notify(); //wait()を例外を発生させて解除する } }
- ngsvx
- ベストアンサー率49% (157/315)
<概要> 各スレッドが順調に動作しているかを監視するためのスレッド(ThreadWatcher)を動かします。 監視対象となるスレッドは、IWatchedThreadインターフェースを実装する必要があります。 ThreadWatcherは設定された周期で各スレッドをチェックし、getTime()メソッドで スレッドが動作している時刻を取得します。 この時刻が現在の時刻より、一定時間過ぎていたら、そのメソッドは停滞しているとみなし、 そのメソッドに対し、doTimeout()メソッドを実行します。 各スレッドは、doTimeout()で停滞を解除するような処理を実行しなければなりません。 今回の場合は、処理のほとんどがループ内で行われているので、 ループ内で、 lastTime = new Date().getTime(); とし、 IWatchedThread#getTime()では、 public long getTime(){ return lastTime; } としておけばいいでしょう。 また、タイムアウト処理は、ストリームをクローズしてしまえばいいと思います。
補足
回答いただきありがとうございます。 こんなにも複雑なコードになるとは、予想するらしていませんでした。本当に、お手数をおかけいたしました。また、ありがとうございます!! そして、このコードを活用すべく、いろいろ本などを見ながら回答があってから、ずっと試行錯誤していたのですが全くもって、うまく動作させられません。 現在、とりあえずは、正常に動作するまでは、下記のテスト用コードを作って、これに作成していただいたコードの追加を考えています。 ここまでしていただいていて、本当に申し訳ないのですが、下記、若しくは#15補足へ、今回作成していただいた新しいコード追加したものを、教えていただけないでしょうか。このコードを扱っていると、自分で何をどうやっているの分からなくなってきました。 interfaceやらsynchronizedやら、たくさんのメソッドが出てきてもう頭が混乱しきっています。 プログラマーの方々がこれを見て、理解できるのが不思議です。途中まで順を追っても、あっちがこっちに影響して、こっちがあっちに影響してと考えているといったい何が何やら・・・ ●Test.java import java.io.*; import java.util.*; import app.webchecker.*; class Test { public static void main(String args[]) throws Exception { System.out.println("In"); for(int a = 0; a<10000; a++) { System.out.print("A"); Thread.sleep(1000);//作為的に停滞状態を作る System.out.println("B"); } System.out.println("Out"); } }
- ngsvx
- ベストアンサー率49% (157/315)
タイムアウト処理を実行させる仕組みです。 説明は後でしますが、とりあえずコードだけお見せします。 ●IWatchedThread.java /* * 作成日: 2004/11/12 * */ package app.webchecker; /** 監視対象となるスレッド * @author ugnag * */ public interface IWatchedThread { /** 動作した時刻を取得します。 * 監視スレッドは、このメソッドの戻り値と、現在の時刻を比較してスレッドが * 動作しているか、停止しているかを判断します。 * 従って、スレッドはこのメソッドの戻り値を頻繁に更新する必要があります。 * * @return 動作確認した最終時刻。スレッドが未実行状態の場合は、-1を返す。 */ public long getTime(); /** タイムアウトの処理を実行します。 * * */ public void doTimeout(); } ●ThreadWatcher.java /* * 作成日: 2004/11/12 * */ package app.webchecker; import java.util.ArrayList; import java.util.Date; import java.util.List; /** スレッドが動作しているか監視する * @author ugnag * */ public class ThreadWatcher implements Runnable { List list = new ArrayList(); long interval = 5000; long time = 1000; volatile boolean cansel = false; /** 監視対象スレッドを追加 * * @author ugnag * * この生成されたコメントの挿入されるテンプレートを変更するため * ウィンドウ > 設定 > Java > コード生成 > コードとコメント */ synchronized public void addWatchedThread(IWatchedThread tr){ list.add(tr); } /** 監視対象スレッドから外す * * @param tr */ synchronized public void removeWatchedThread(IWatchedThread tr){ list.remove(tr); } /** 監視間隔の設定 * * @param interval */ public void setInterval(long interval){ this.interval = interval; } /** タイムアウトと判定される時間の設定 * * @param time */ public void setTime(long time){ this.time = time; } /** 監視の実行 * * */ public void startPatrol(){ Thread t = new Thread(this); t.start(); } /** 監視の終了 * * */ synchronized public void stopPatrol(){ cansel = true; } /** * * @return */ synchronized public boolean isCanseled(){ return cansel; } /** * */ public void run(){ while(!isCanseled()){ watchThreads(); try { Thread.sleep(interval); } catch (InterruptedException e) { } } } /** * * */ synchronized protected void watchThreads(){ int n = list.size(); for(int i = 0 ; i < n ; i++){ IWatchedThread thread = (IWatchedThread)list.get(i); if( (thread instanceof Runnable) || (thread instanceof Thread) ){ if(thread.getTime() != -1){ long lastTime = thread.getTime(); long now = new Date().getTime(); if(time < now - lastTime){ thread.doTimeout(); } } } } } }
- ngsvx
- ベストアンサー率49% (157/315)
出張やらなんやらで、時間がとれない状態です。 来週になればお見せできると思います。 もう少し、待ってて下さい。 *一応、できてはいるのですが、テストしていないので。。。
補足
あせらせてしまって、すみません。 お仕事、優先でがんばって下さい。 コード、楽しみにしています。
- ngsvx
- ベストアンサー率49% (157/315)
ひとつ確認しておきたいのですが、 止まるのは、ストリームの読み込みで、 ストリームの取得自体は出来たのですよね? InputStream is = url.openStream(); が実行されたかどうかです。 ストリームの取得まで成功しているなら、 うまくいきそうです。
お礼
ngsvxさん こんにちは。少なくともひとつは、原因がはっきりしたので補足です。 Kaiseki2の下記部分を、 ------------------------------ for (;;) { String i = in.readLine(); if( i == null) {break;} ------------------------------ ↓ ------------------------------ for (;;) { String i = in.readLine(); if( i.indexOf("</HTML>") > 0) {break;} if( i.indexOf("</html>") > 0) {break;} if( i == null) {break;} ------------------------------ と変更すると、今のところ、末端が、htmlで閉じてあるHPに関しては止まることなくうまくいきます。 この事から、#16ご指摘のように、ストリームの途中で読み込みができなくなっていたようです。 ただ、タイムアウトというよりは、末端辺りまで読み込んでも、nullを検出できないため、止まっていたようです。 しかし、正確なHTMLで記述してない場合や末端辺りにいくまでにストリームの読み込みが止まった場合など全く対応できません。 多分、このコードを書くには、かなりの技量不足なので、もし、可能でしたら回答宜しくお願い致します。 少し、質問です。 こういったエラー防止の最終手段として、ストリームの読み込み時間を60秒以内に制限するとかといったことは可能でしょうか? また、今回のように、nullを検出できなかったため、なんのエラー表示もなく、ただ止まるというエラーになっていたようですが、こういった場合エラーの排出をさせる方法ってないのでしょうか?今回のエラー検出にはものすごく苦労しています。 ちょっと、古いPCでも動きをチェックしてみたくて、 Celeron 466MHz、Win98Seという昔のThinkPadで作業してみました。そうすると、このエラーが顕著に現れたためエラーの発見が容易でした。古いパソコンだと、新しいパソコンに比べてかなり厳しくエラーがでるのですがなぜでしょうか??? 以上、わかる部分だけでもいいので、ご回答宜しくお願い致します。
補足
お忙しい中ご返答いただきありがとうございます。 その部分に関しては、エラーログを見直してみたところ、まず間違いなく成功していると思います。 宜しくお願い致します。 ちなみに、今、本の方は、75ページまで読みました。 クラスって思いつきで分けてたんですが、実は、こんな風にして分けるんですね。ぜんぜん知りませんでした!!
- ngsvx
- ベストアンサー率49% (157/315)
>で停止していましたので、やはり、読み込み途中で停止しているようです。 2つの方法を思いついて、1つを試したのですが、 うまくいかないようでした。 もうひとつの方法を試してみます。 今、仕事が忙しくなってきたので、2~3日お待ち下さい。
- ngsvx
- ベストアンサー率49% (157/315)
とりあえず、#16の推測が正しいかテストしておいて下さい。 読み込みのループのとき、 System.out.println("read 前(" + id + ")"); for (;;) { String i = in.readLine(); System.out.println("read 中(" + id + ")"); if( i == null) {break;} if(i.indexOf("http")!=-1){ fr.write(i.indexOf("http")+"\n"); } } System.out.println("read 後(" + id + ")"); とでもしておけばわかると思います。 (どうだったかだけ知らせてくだされば結構です) タイムアウトの件は、休みの間に考えておきます。 ただ、このプログラムを拡張する気があるのなら、 やはり、根本的なところを見直した方がいいと思うのですが・・・。 スレッドやソケットを使いすぎると、CPUが動作しにくくなったり、リソースの消費のためOSが不安定になったり、あまりいいことはないです。 どのくらいが適切かというのは、環境等によりますので一概には言えませんが、多くて10個程度ではないかと・・・。 他のプロセスもスレッドを使うことを考えると、リソースの独り占めはよくないと思います。(^^;
補足
■スレッド数について 少し前に、Pentium4 3GHz、WindowsXP、メモリ768MBくらいのスペックで自作したので、マシーン能力だけでしたら、ある程度は大丈夫かと思っています。ただ、いろんなソフトが入って少し不安定なのが問題ですが・・・ ■推測の件に関して read 中(76) read 中(76) read 中(76) で停止していましたので、やはり、読み込み途中で停止しているようです。 ■#12お礼欄のエラーに関して なんとなく、タイミングがおかしいのかと思って、Testの部分に一時停止を入れてみました。 とりあえずは、始まってすぐにとまるというエラーは起こらなくなったので成功かと思っています。 ただ、こんな単純?な引継ぎすら失敗することってそもそも良くあることなのでしょうか? また、より、タフなプログラムにするためには、いたる所に一時停止を入れたほうが良いのでしょうか? int setLoop = 10; int loop = 0; int count = 0; Kaiseki2 run[] = new Kaiseki2[lineCnt]; for(int cnt=0; cnt<lineCnt; cnt++) { System.out.println(h2[cnt]); Thread.sleep(10);//<<<新しく追加したところ run[cnt] = new Kaiseki2(h2[cnt],cnt); ■全般に関して このようにして、エラーを発見して、デバッグしていくのですね。とても勉強になっています。ありがとうございます。また、お休みの日に考えていただけるのこと、とても感謝です。本当に、ありがとうございます。 >ただ、このプログラムを拡張する気があるのなら、 >やはり、根本的なところを見直した方がいいと思うのですが・・・。 このプログラムをそのまま拡張するかどうかはまだ未定ですが、少なくとも、他のプログラムを書く際には、エラー処理のしてある有用なコードはどんどん活用しながら書いていく予定です。ところで、根本といいますと、どういったところでしょうか?いまいちわかりません。
- ngsvx
- ベストアンサー率49% (157/315)
●動作停止の件(続き) あくまでも想像ですが、今までの状況からして、 ストリームの読み込みで止まっている気がします。 つまり、接続先のサーバーから応答がない。 しかも、向こうがタイムアウトでの切断をして くれないのでは、という気がします。 もしそうだとすると、読み込みにタイムアウトの設定は出来ないので、仕掛けを作る必要がありますね。 現時点では、あくまでも推測の域をでない話でした。
お礼
昨日、アマゾンから、本が届きました。 読んではいるのですがさすがに、難しいですね。とりあえず、クラスの作成が何だが重要そう。。。
お礼
長らく、回答いただき本当に、ありがとうございました。今、コードを勉強する時間がどうしても取れないため、また、時間が取れる時がありましたら新しく質問させていただきますので、その際は、ぜひ、お付き合いよろしくお願いいたします。