dポイントプレゼントキャンペーン実施中!

JAVAを使って、ホームページを読み込んでいるのですが、100000ページくらいのURLを読み込んだ辺りでよく止まってしまいます。なぜでしょうか?
また、JAVAがURLを読み込んでいる時に、メールチェックをしたり、たくさんのホームページをIEで見ていても止まることが良くあります。
こういったエラー表示の出ないエラーを解決するにはどうしたらよいでしょうか?とても困っています。
教えていただけないでしょうか?
宜しくお願い致します。

A 回答 (26件中11~20件)

●動作停止の件(続き)



 あくまでも想像ですが、今までの状況からして、
ストリームの読み込みで止まっている気がします。

つまり、接続先のサーバーから応答がない。
しかも、向こうがタイムアウトでの切断をして
くれないのでは、という気がします。

もしそうだとすると、読み込みにタイムアウトの設定は出来ないので、仕掛けを作る必要がありますね。

現時点では、あくまでも推測の域をでない話でした。
    • good
    • 0
この回答へのお礼

昨日、アマゾンから、本が届きました。
読んではいるのですがさすがに、難しいですね。とりあえず、クラスの作成が何だが重要そう。。。

お礼日時:2004/11/14 03:43

あいかわらず、私の環境では発生しません。




●java.net.BindException: Address already in use: connectの件

 スレッド(というよりソケット)が多すぎるのだと思います。
ドキュメントを見ると、

「ローカルなアドレスおよびポートに対してソケットのバインドを試行中に
エラーが発生したことを通知します。
 一般的には、ポートが使用中であるか、要求したローカルアドレス割り当てが
できないことが原因です。 」

---JavaAPIより---


詳しくはわかりませんが、ルータを使っているということなので、その辺りで
出てるのではないかと。。。(^^;

いずれにしても、スレッドやソケットを50個も使うのは多すぎますね。
(非常識な行為と言われますよ)


●動作停止の件

 #13の補足ですが、コードをいじってません?
「30休憩」のメッセージの出かたがおかしいのですけど。

この回答への補足

import java.net.*;
import java.io.*;

class Test {
public static void main(String args[]) throws IOException{
try {
InputStream is = new FileInputStream("URL.dat");
BufferedReader br = new BufferedReader(new InputStreamReader(is));

String h;
int lineCnt = 0;
for(;;) {
h = br.readLine();
if(h == null) {break;}
lineCnt ++;
}
br.close();
is.close();


InputStream is2 = new FileInputStream("URL.dat");
BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));
String h2[] = new String[lineCnt];
for(int h2Cnt=0; h2Cnt<lineCnt; h2Cnt++) {
h2[h2Cnt] = br2.readLine();
}
br2.close();
is2.close();


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]);
run[cnt] = new Kaiseki2(h2[cnt],cnt);
run[cnt].start();
loop++;
if(loop == setLoop){
count = loop + count;
int loopJoin = 0;
loopJoin = cnt + 1 - setLoop;
for(int i=1; i<=setLoop; i++){
run[loopJoin].join();
loopJoin++;
loop=0;
}
System.out.println("Test() "+": "+count);
System.out.println("30休憩");
Thread.sleep(30000);//30休憩
}
}


int reJoin = lineCnt%setLoop;
int reloop = lineCnt - reJoin;
for(int i=1; i<=reJoin; i++){
run[reloop].join();
reloop++;
}
System.out.println("Test(Finish) "+": "+reloop);

if(reloop == lineCnt){System.out.println("O.K.");}else{System.out.println("Err");}

}catch(Exception ex){
System.out.println("エラー:Test()");
System.out.println(ex.getMessage());
}
}
}


class Kaiseki2 extends Thread {
private String h = null;
private int id;

Kaiseki2(String str,int id) {
this.h = str;
this.id = id;
}

public void run() {

System.out.println(id + " start");

int LOOP_MAX = 10;
int loopcnt = 0;
try {
OutputStream os = new FileOutputStream("出力.txt",true);
BufferedWriter fr = new BufferedWriter(new OutputStreamWriter(os));
URL url = new URL(h);
while(loopcnt < LOOP_MAX){
try{

System.out.println(id + " ストリーム取得開始");
InputStream is = url.openStream();
System.out.println(id + " ストリーム取得終了");
BufferedReader in = new BufferedReader(new InputStreamReader(is,"JISAutoDetect"));

for (;;) {
String i = in.readLine();
if( i == null) {break;}

if(i.indexOf("http")!=-1){
fr.write(i.indexOf("http")+"\n");
}
}
in.close();
break;

}catch(Exception e){
loopcnt ++;
System.out.println(url);
System.out.println(loopcnt);
System.out.println("20秒休憩"); // ウェイト処理
e.printStackTrace();
System.out.println(e.getMessage());
Thread.sleep(20000);
}
}
fr.close();System.out.println("30休憩");
os.close();//外に出すこと
}catch(Exception ex){System.out.println("エラー:Kaiseki2()");System.out.println(ex.getMessage());}
System.out.println(id + " end");
}
}

補足日時:2004/11/12 15:03
    • good
    • 0
この回答へのお礼

お返事いただき、ありがとうございます。
返信です。

>つまり、接続先のサーバーから応答がない。
>しかも、向こうがタイムアウトでの切断をして
>くれないのでは、という気がします。
>もしそうだとすると、読み込みにタイムアウトの設定は出来ないので、仕掛けを作る必要がありますね。

もしかすると、ADSLのため、通信回線の不安定さが原因かもしれません。
また、ソケットが重複するとのことですが、このJAVAプログラムを動かしているにOutlookExpress(以下、OE)を使うと
Address already in use: connect
がでたり、
プログラムが止まったり
して、普通にOEが使えず困っています。また、これから先、このソフトをADSLよりも不安定な、AirH”で使う可能性もあるため、
通信が不安定な環境でもタフに動いてくれるプログラムを作りたいと思っています。
どのようなコードになりますか。もしよろしければ、記述していただけないでしょうか?



>詳しくはわかりませんが、ルータを使っているということなので、その辺りで
>出てるのではないかと。。。(^^;

ルーター内臓のADSLモデムを、ハブで分けているので原因かと思ってとりあえず、直接ルーターに
つないで見たいのですが、相変わらず先と同じエラーがでます。



>いずれにしても、スレッドやソケットを50個も使うのは多すぎますね。
>(非常識な行為と言われますよ)

どのくらいの数が適切なのでしょうか?
また、これに対するまずさはどの辺りでしょうか?
以前、質問したときも、この件に関してはかなり指摘がありました。
一番いいのは、スレッド、ソケット数どちらにしても、マシーンや回線速度にマッチした最適が出せればいいのですが・・・


>●動作停止の件
> #13の補足ですが、コードをいじってません?
>「30休憩」のメッセージの出かたがおかしいのですけど。

コードは、指摘されたところ意外、特にいじっていませんが、
念のため補足に記述しておきます。

お礼日時:2004/11/12 15:05

すみません。

さらにもう1つ。

BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(),"JISAutoDetect"));



System.out.println(id + " ストリーム取得開始");
InputStream is = url.openStream();
System.out.println(id + " ストリーム取得終了");

BufferedReader in = new BufferedReader(new InputStreamReader(is,"JISAutoDetect"));

としてみて下さい。

この回答への補足

もうひとつ、エラーのほうが発生いたしましたので、記載いたします。
宜しくお願い致します。
----------------------------------
37 start
38 start
39 start
http://www.itar-tass.com/
http://www.afp.com/
http://www.unian.net/
http://www.spa.gov.sa/
http://www.nampa.org/
http://www.iha.com.tr/bin/directory.dll/pf
22 ストリーム取得開始
21 ストリーム取得開始
40 start
41 start
42 start
43 start
44 start
45 start
http://www.anp.nl/
http://www.tvguide.or.jp/cgi-bin/top.cgi
http://www.aniin.com/
24 ストリーム取得開始
23 ストリーム取得開始
46 start
47 start
48 start
49 start
4 ストリーム取得開始
26 ストリーム取得開始
25 ストリーム取得開始
5 ストリーム取得開始
9 ストリーム取得開始
27 ストリーム取得開始
12 ストリーム取得開始
13 ストリーム取得開始
14 ストリーム取得開始
28 ストリーム取得開始
29 ストリーム取得開始
31 ストリーム取得開始
30 ストリーム取得開始
33 ストリーム取得開始
32 ストリーム取得開始
8 ストリーム取得開始
7 ストリーム取得開始
35 ストリーム取得開始
34 ストリーム取得開始
11 ストリーム取得開始
15 ストリーム取得開始
10 ストリーム取得開始
36 ストリーム取得開始
16 ストリーム取得開始
6 ストリーム取得開始
39 ストリーム取得開始
38 ストリーム取得開始
41 ストリーム取得開始
40 ストリーム取得開始
43 ストリーム取得開始
42 ストリーム取得開始
47 ストリーム取得開始
44 ストリーム取得開始
45 ストリーム取得開始
37 ストリーム取得開始
49 ストリーム取得開始
48 ストリーム取得開始
46 ストリーム取得開始
http://jahon.mfa.uz/english.html
1
20秒休憩
http://www.aniin.com/
1
20秒休憩
http://www.itar-tass.com/
1
20秒休憩
http://www.paknews.com/
1
20秒休憩
http://www.habena.ba/
1
20秒休憩
http://www.yonhapnews.co.kr/
1
20秒休憩
48 ストリーム取得終了
http://www.europapress.es/
1
20秒休憩
http://www.jamahiriyanews.com/
1
20秒休憩
27 ストリーム取得終了
30休憩
48 end
java.net.BindException: Address already in use: connect30休憩
27 end
14 ストリーム取得終了
33 ストリーム取得終了
47 ストリーム取得終了

at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(Unknown Source)
at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at sun.net.NetworkClient.doConnect(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient.<init>(Unknown Source)38 ストリーム取得終了
24 ストリーム取得終了
12 ストリーム取得終了
17 ストリーム取得終了
36 ストリーム取得終了
16 ストリーム取得終了
Address already in use: connect
4 ストリーム取得終了
30休憩
38 end
30休憩
16 end
30休憩
36 end
30休憩
4 end
30休憩

補足日時:2004/11/11 18:38
    • good
    • 0
この回答へのお礼

追伸
このエラーは、
Test

int setLoop = 10;→int setLoop = 50;
にして実験しています。
また、このエラーが起こる前には、インターネット(インターネットエクスプローラー)でたくさんのページを観覧したり、このJAVAプログラムを立ち上げて、閉じた後でした。

お礼日時:2004/11/11 18:44

すみませN、もう1箇所。



Kaiseki2のループ中の例外キャッチで、1行追加して下さい。


loopcnt ++;
System.out.println(url);
System.out.println(loopcnt);
System.out.println("20秒休憩"); // ウェイト処理
System.out.println(e.getMessage());
e.printStackTrace(); //<---追加
Thread.sleep(20000);

この回答への補足

もうひとつエラーが発生しました。
これが表示された状態で全く先に進みません。もうすでに、15分間、動いていません。
あと、このプログラムを動作させている時,
時々、インターネットに一切つながらなくなるというエラーが起きます。もしかすると、これも関係ありますかね?
因みに、同一のルーターから分配されているパソコンでは問題なくホームページが見れます。また、この繋がらないという状態が復旧した後も、プログラムは停止したままです。
宜しくお願い致します。

-------------------------------------
http://www.pakistan-news.com/
67 start
67 ストリーム取得開始
68 start
68 ストリーム取得開始
63 start
63 ストリーム取得開始
69 start
69 ストリーム取得開始
60 ストリーム取得終了
30休憩
60 end
66 ストリーム取得終了
30休憩
66 end
61 ストリーム取得終了
30休憩
61 end
63 ストリーム取得終了
62 ストリーム取得終了
68 ストリーム取得終了
30休憩
68 end
67 ストリーム取得終了
64 ストリーム取得終了
30休憩
64 end
30休憩
63 end
30休憩
67 end
65 ストリーム取得終了
30休憩
65 end
69 ストリーム取得終了
30休憩
69 end
30休憩
62 end
Test() : 70
30休憩
http://www.ips.org/
http://www.tanjug.co.yu/
http://www.jiji.com/
http://www.site.kz/news.php
http://www.bns.ee/
http://www.cananews.com/
70 start
70 ストリーム取得開始
71 start
71 ストリーム取得開始
72 start
72 ストリーム取得開始
73 start
73 ストリーム取得開始
74 start
74 ストリーム取得開始
http://www.noyan-tapan.am/
http://www.ndn-news.co.jp/
http://www.armenpress.am/
http://www.kyodo.co.jp/
75 start
75 ストリーム取得開始
76 start
76 ストリーム取得開始
77 start
77 ストリーム取得開始
78 start
78 ストリーム取得開始
79 start
79 ストリーム取得開始
72 ストリーム取得終了
30休憩
72 end
77 ストリーム取得終了
79 ストリーム取得終了
30休憩
77 end
30休憩
79 end
75 ストリーム取得終了
30休憩
75 end
73 ストリーム取得終了
70 ストリーム取得終了
71 ストリーム取得終了
30休憩
71 end
30休憩
70 end
30休憩
73 end
78 ストリーム取得終了
30休憩
78 end
74 ストリーム取得終了
30休憩
74 end
76 ストリーム取得終了
-------------------------------------

補足日時:2004/11/11 17:18
    • good
    • 0

困りました。

ソースを動かしましたがなかなか現象が発生しません。

とりあえず、そちらでも次のことをしてみて下さい。

まずは、どこで動かなくなっているのかを特定しましょう。

スレッドの開始と終了時にメッセージを出します。
ただ出したのでは、どのスレッドかわからないので、

Kaiseki2を

class Kaiseki2 extends Thread {
 private String h = null;
 private int id;

 Kaiseki2(String str, int id) {
  this.h = str;
  this.id = id;
 }

とします。


あとは、runメソッドの開始に
System.out.println(id + " start");

終了に、
System.out.println(id + " end");

とします。


Testクラスでは、

for(int cnt=0; cnt<lineCnt; cnt++) {
 System.out.println(h2[cnt]);       //<----コメントを外す
 run[cnt] = new Kaiseki2(h2[cnt], cnt); // <----変更
 run[cnt].start();

と直します。

こうして、どこで止まっているのかを限定して下さい。


●本の件

 例はC++で書いてありますが、メインはコードではなく考え方ですし、
書いてあるコードも難しいものではないので、問題はないと思います。

この回答への補足

----------------------------------------------
22 ストリーム取得終了
30休憩
22 end
Test() : 30
30休憩
http://www.cp.org/
http://www.montsame.mn/
30 start
30 ストリーム取得開始
http://www.mti.hu/
http://www.interfax-news.com/
http://www.lusa.pt/
http://www.zana.gov.zm/
http://www.bulls.no/
http://www.upi.com/
31 start
31 ストリーム取得開始
32 start
32 ストリーム取得開始
33 start
33 ストリーム取得開始
34 start
34 ストリーム取得開始
35 start
35 ストリーム取得開始
36 start
36 ストリーム取得開始
http://www.adi.dj/
http://www.anadoluajansi.com.tr/
37 start
37 ストリーム取得開始
38 start
38 ストリーム取得開始
39 start
39 ストリーム取得開始
37 ストリーム取得終了
30休憩
37 end
30 ストリーム取得終了
30休憩
30 end
33 ストリーム取得終了
30休憩
33 end
36 ストリーム取得終了
30休憩
36 end
32 ストリーム取得終了
38 ストリーム取得終了
30休憩
38 end
34 ストリーム取得終了
35 ストリーム取得終了
30休憩
32 end
30休憩
34 end
30休憩
35 end
31 ストリーム取得終了
30休憩
31 end
http://www.anadoluajansi.com.tr/
1
20秒休憩
java.net.UnknownHostException: www.anadoluajansi.com.trwww.anadoluajansi.com.tr

at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at sun.net.NetworkClient.doConnect(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient.<init>(Unknown Source)
at sun.net.www.http.HttpClient.<init>(Unknown Source)
at sun.net.www.http.HttpClient.New(Unknown Source)
at sun.net.www.http.HttpClient.New(Unknown Source)
at sun.net.www.http.HttpClient.New(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.net.URL.openStream(Unknown Source)
at Kaiseki2.run(Test.java:99)
39 ストリーム取得開始
http://www.anadoluajansi.com.tr/
2
20秒休憩
java.net.UnknownHostException: www.anadoluajansi.com.trwww.anadoluajansi.com.tr

at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at sun.net.NetworkClient.doConnect(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient.openServer(Unknown Source)
at sun.net.www.http.HttpClient.<init>(Unknown Source)
at sun.net.www.http.HttpClient.<init>(Unknown Source)
at sun.net.www.http.HttpClient.New(Unknown Source)
at sun.net.www.http.HttpClient.New(Unknown Source)
at sun.net.www.http.HttpClient.New(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.net.URL.openStream(Unknown Source)
at Kaiseki2.run(Test.java:99)
39 ストリーム取得開始
39 ストリーム取得終了
30休憩
39 end
Test() : 40
30休憩
----------------------------------------------

補足日時:2004/11/11 17:10
    • good
    • 0
この回答へのお礼

■本の件
なるほど!了解しました。
とりあえず、オンラインショップで購入してみます。
因みに、今は、ソフトをGUIで使いたいので
やさしいJAVA活用編を読解中です。
エラーについては記述容量に限りがあるので、補足やお礼にて書いていきますので、宜しくお願い致します。

■プログラムの件
今確認できたエラーは2つ
■1つは、URLがもとより読めないケース
表示された画面は下記の通り


■それでも、何度か、プログラムを立ち上げては閉じ、
を繰り返していると、作動する。
動作したときに起こったエラーは最下段の通り、
しかし、3度目のトライで無事読めたため次に移った模様。
そのため、今は、正常に次のURLを読んでいる模様。
----------------------------------------------
http://jahon.mfa.uz/english.html
http://www.ceskenoviny.cz/news/
http://www.sapa.org.za/
0 start
0 ストリーム取得開始
1 start
1 ストリーム取得開始
http://www.aman-alliance.org/
http://www.nni-news.com/
3 start
2 start
http://www.aib.bf/
http://www.presseamt.li/
http://www.wafa.pna.net/
http://www.yonhapnews.co.kr/
http://www.telam.com.ar/
4 start
5 start
6 start
7 start
8 start
9 start
----------------------------------------------

お礼日時:2004/11/11 17:11

えーっと、「とりあえず動くようにしたい」ということだと理解しましたけど、いいでしょうか?




でしたら、

1.エラーメッセージの正確な内容。
2.その時のソース(#9から何も変えていなければそれで結構です)。
3.URL.DATの件数

は必須ですので、それを提示して下さい。



オブジェクト指向の件は、勉強しておいた方がいいと思いますよ。
きれいなプログラムを作れるようになるかもしれません。
きれいなプログラムは、バグが出にくく、デバッグもしやすく、拡張もしやすいという傾向がありますから。。。

この回答への補足

2.ソース
Test.java
-----------------------------
import java.net.*;
import java.io.*;

class Test {
public static void main(String args[]) throws IOException{
try {
InputStream is = new FileInputStream("URL.dat");
BufferedReader br = new BufferedReader(new InputStreamReader(is));

String h;
int lineCnt = 0;
for(;;) {
h = br.readLine();
if(h == null) {break;}
lineCnt ++;
}
br.close();
is.close();


InputStream is2 = new FileInputStream("URL.dat");
BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));
String h2[] = new String[lineCnt];
for(int h2Cnt=0; h2Cnt<lineCnt; h2Cnt++) {
h2[h2Cnt] = br2.readLine();
}
br2.close();
is2.close();


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]);
run[cnt] = new Kaiseki2(h2[cnt]);
run[cnt].start();
loop++;
if(loop == setLoop){
count = loop + count;
int loopJoin = 0;
loopJoin = cnt + 1 - setLoop;
for(int i=1; i<=setLoop; i++){
run[loopJoin].join();
loopJoin++;
loop=0;
}
System.out.println("Test() "+": "+count);
System.out.println("30休憩");
Thread.sleep(30000);//30休憩
}
}


int reJoin = lineCnt%setLoop;
int reloop = lineCnt - reJoin;
for(int i=1; i<=reJoin; i++){
run[reloop].join();
reloop++;
}
System.out.println("Test(Finish) "+": "+reloop);

if(reloop == lineCnt){System.out.println("O.K.");}else{System.out.println("Err");}

}catch(Exception ex){
System.out.println("エラー:Test()");
System.out.println(ex.getMessage());
}
}
}


class Kaiseki2 extends Thread {
private String h = null;

Kaiseki2(String str) {
this.h = str;
}

public void run() {

int LOOP_MAX = 10;
int loopcnt = 0;
try {
OutputStream os = new FileOutputStream("出力.txt",true);
BufferedWriter fr = new BufferedWriter(new OutputStreamWriter(os));
URL url = new URL(h);
while(loopcnt < LOOP_MAX){
try{
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(),"JISAutoDetect"));
for (;;) {
String i = in.readLine();
if( i == null) {break;}

if(i.indexOf("http")!=-1){
fr.write(i.indexOf("http")+"\n");
}
}
in.close();
break;

}catch(Exception e){
loopcnt ++;
System.out.println(url);
System.out.println(loopcnt);
System.out.println("20秒休憩"); // ウェイト処理
System.out.println(e.getMessage());
Thread.sleep(20000);
}
}
fr.close();
os.close();//外に出すこと
}catch(Exception ex){System.out.println("エラー:Kaiseki2()");System.out.println(ex.getMessage());}
}
}
-----------------------------

補足日時:2004/11/11 10:09
    • good
    • 0
この回答へのお礼

文字数の関係で#10、11のお礼欄も質問に使わせていただきます。あらかじめ、ご了承下さい。

■オブジェクト指向の件と本について
長所がたくさんあるようなので、是非、勉強したいですね。しかし、書籍紹介についてですが、C++がベースになっているのはどうかと。できれば、JAVAに直接関係ある書籍のほうが嬉しいのですが・・・それとも、この本でも、きれいなソースやオブジェクト指向をを書くという意味では、どちらでもあまり関係ないですかね?どうでしょうか?

■動くプログラムにしたい件について

えーっと、「とりあえず動くようにしたい」ということだと理解しましたけど、いいでしょうか?
はい!よろしくお願いいたします!!
もう、私にはお手上げ状態だったのでとてもありがたいです!!!!
以下、情報です。分からないことがあったらなんでも聞いてください。


1.エラーメッセージの正確な内容。
>>当、書き込み

2.その時のソース(#9から何も変えていなければそれで結構です)。
>>補足参照

3.URL.DATの件数
>>#10お礼欄参照


1.エラーメッセージが表示されない状態でプログラムが先に進まない。
1時間たっても先に進みません・・・
また、エラーの表示画面がなぜかされないので、画面に、表示されたものを書いておきます。
再現性については、あったりなかったりと、これという理由が思い当たりません。
もしかすると、WindowsXpが不安定??しかし、JAVAを動かす前に、
再起動してその後は、マウスすら触らなくても同様のことが起こることもある。
起こらず、Test() : 60も正常に表示されることもある。
しかし、続けていると、いつの間にかエラー表示がない状態で止まる。
----------------
Test() : 20
30休憩
Test() : 40
30休憩
----------------

お礼日時:2004/11/11 10:08

●動作保証がない件



 あのソースでは、各スレッドが同一のファイルをオープン・書き込みを
しています。これはいいですよね?

 つまり、スレッドAがファイルをオープン・書き込みしている最中に、
スレッドBが同じファイルに対し、オープン・書き込みをしようとするわけです。

 このときの動作はOS等に依存すると思います。
 つまり、あのプログラムは動作保証がないということになります。


●オブジェクトをスレッドに渡す件

 例えば、InputStreamなどのオブジェクトを各スレッドに渡すということです。
ただし、InputStreamそのものは同期化対応されてないので、これを同期化させた
オブジェクトに改造する必要があります。

 同期化されていないと、スレッドAが「ABCDE」、スレッドBが「123456」
という書き込みが同時に実行された場合、ファイルには「A1BC234D5E6」などのように
なる可能性があるからです。


●勉強方法・教科書等の件

 ちょっと言い方が悪いかもしれませんが、もともにというか、まじめにというか、
正しい学習方法は、JAVA言語からではなく、オブジェクト指向の概念を
学ぶことから始めることです。

 JAVA言語というのはオブジェクト指向の概念を具体化するためのものなのです。

 「クラス」、「継承」、「汎化」などはオブジェクト指向の用語です。
この概念を知らないでJAVA言語を使うのは、英語を覚えた普通の日本人が、
アメリカ人の大学教授と、彼の専門分野に関して会話をするのと同じ事です。
言葉そのものは話せても、会話にはならないでしょう。

 その意味から、オブジェクト指向の概念を学ぶのが本道です。

 ただ、このような、概念を理解するのは難しいので、本を1冊読んだだけで済むとは
思わないでください。数冊読んでなんとなくわかるものです。

 今は、書籍も多く出ているので、「オブジェクト指向」をキーワードで探せば直ぐに見つかると
思います。簡単そうなのを選んで下さい。

 私が好きなのは、「憂鬱なプログラマのためのオブジェクト指向開発講座」という本です。
これを読んで、目から鱗が落ちました。

 難点を言えば例がC++で記述されていること、表記方法が現在主流のUMLではないことです。
しかし、オブジェクト指向の概念を学ぶのには良い本だと思います。

http://www.amazon.co.jp/exec/obidos/ASIN/4881356 …


●質問

 前回の質問では、Webページを監視し続けるプログラムを作りたいとのことでしたが、
今回のプログラムでは、リストアップされたページをダウンロードして終わりのようです。
方向転換したのですか?


●その他

 全体構造を見直すつもりがあるのなら、手伝いますけどどうします?
 ただし、少し時間はかかるかもしれませんけど(会話に)。

この回答への補足

丁寧な、回答いただき本当にありがとうございます。
動作保証がない件、オブジェクトをスレッドに渡す件、一応理解できました。ありがとうございます。

教科書・勉強の件
オブジェクト指向からですか・・・
確かに、一度勉強してみてもいい気もしています。逆に、習うより慣れろで、どんどん、コードを書いてある程度使えるようになってから専門書を読む方がより円滑に学習ができるかもという期待もあります。いずれにしても、とりあえずは、本の方を入手してみようと思います。

例え>専門化との会話
会話にならない。確かにそうかもしれませんが、一般的なことでしたらまだ、カバーできるのではないかと思いますがいかがでしょうか。自分がどのくらいのレベルにあるのかが分からないのでなんともいえませんが、少なくとも、今回のプログラム位であれば少しの助言があれば結構簡単にデバッグできるのではないかと思っているのですが、難しいでしょうか?もしよろしければ、このプログラムを正常に動作させるコードを教えていただけないでしょうか?

#9の動作、報告です
全ての読み込みに、同期を取ると、気持ちのせいかもしれませんが、どことなく、安定した感(address already in use: connect javaエラーの数が減った気がする)はあるのですが、
・address already in use: connect java
・Unexcepted end of file from server
・エラー表示せずに止まる
上記3つのエラーが依然でます。
もしよろしければ、このコードを正常に動作させるJAVAプログラムを教えていただけないでしょうか?
宜しくお願い致します。


方向転換したのですか?
>とりあえず、このエラーがなくなるまでは前に進めそうにありません。全てを自動化しなくても、取得したデータをExcelに入力するとJAVAでするよりも遥かに手軽にできるため、全自動化はあまり急いでいません。とりあえずは、このコードをまともに動作させることに勤めたいと思っています。

補足日時:2004/11/10 13:53
    • good
    • 0
この回答へのお礼

URL.dat
(こんな感じのものが140件つづきます。140件以降は、もう一度始めに戻って繰り返しです。プログラム制御ではなく、実際のURL.datはコピーの繰り返しで代用しています。
例:
URL1
URL2
・・・
・・・
URL139
URL140
URL1
URL2
・・・
・・・
URL140


----------------
http://jahon.mfa.uz/english.html
http://www.ceskenoviny.cz/news/
http://www.sapa.org.za/
http://www.aman-alliance.org/
http://www.nni-news.com/
http://www.aib.bf/
http://www.presseamt.li/
http://www.wafa.pna.net/
http://www.yonhapnews.co.kr/
http://www.telam.com.ar/
http://www.jamahiriyanews.com/
http://www.np-net.co.jp/
http://www.ansa.it/
http://www.noticiasargentinas.com/
http://www.omannews.com/
http://www.kplnet.net/
http://www.inforpressca.com/inforpress/
http://www.irna.com/en/
http://www.adn.de/
http://www.dinau.com/
http://www.sofiapress.bg/index_en.htm
http://www.fides.org/
http://www.habena.ba/
http://www.paknews.com/
http://www.reuters.com/
http://www.aps.dz/
http://www.srna.co.yu/
http://china.kyodo.co.jp/
http://www.ana.gr/
http://www.agenceurope.com/
http://www.cp.org/
http://www.montsame.mn/
http://www.mti.hu/
http://www.interfax-news.com/
http://www.lusa.pt/
http://www.zana.gov.zm/
http://www.bulls.no/
http://www.upi.com/
http://www.adi.dj/
http://www.anadoluajansi.com.tr/
http://www.europapress.es/
http://www.itar-tass.com/
http://www.afp.com/
http://www.unian.net/
http://www.spa.gov.sa/
http://www.nampa.org/
http://www.iha.com.tr/bin/directory.dll/pf
http://www.anp.nl/
http://www.tvguide.or.jp/cgi-bin/top.cgi
http://www.lena.gov.ls/news.htm
http://www.aniin.com/

お礼日時:2004/11/11 10:13

質問とは直接関係がないので書かなかったのですが、



1.配列のインデックスは0から使えます(普通0から使います)
2.mainメソッド内の、
  String h[] = new String[cnt];
  h[cnt-1] = br.readLine();
  は配列にしている意味がありません。
  毎回、配列が初期化されています。
3.出力ファイル「出力.txt」は各スレッドで使うため、動作が保証されないと思います。
4.Kaiseki2#run()メソッドのwhileループでは、2回目のループで、閉じられた出力ファイル(fr)に対して書き込みをしようとしています(fr.write(i+"\n");)。


1,2に関しては、まずファイルの内容を全てjava.util.ArrayListに読み込んでしまったらいいと思います。

3は、一時ファイルを使うか、スレッドにidを付けておいて、ファイル名にそのidを付加する
ことで、スレッド毎に違う名前になります。
もし、全てのスレッドが同じファイルに書き込みをしたいのなら、ちょっと仕掛けが必要です。
出力ファイルアクセス用のクラスを作って、そのオブジェクトをスレッドに渡します。
スレッドから使用される、ファイル書き込み用のメソッドは同期メソッドにしておく必要があります。

4は何をしたいのかがわからないので、アドバイスできません。

この回答への補足

上記のアドバイスを参考にして作り直してみました。
少しばかり、無駄が多いプログラムの気もしますが、まともに動作していますので、最新のコードを記載いたします。
なお、以前と同じエラーが出るか否かについては、今、ADSL回線がまともに使えない場所に居ますので、後ほどレポートさせていただきます。
何か、良いアドバイスがありましたら、宜しくお願い致します。


import java.net.*;
import java.io.*;

class Test {
public static void main(String args[]) throws IOException{
try {
InputStream is = new FileInputStream("URL.dat");
BufferedReader br = new BufferedReader(new InputStreamReader(is));

String h;
int lineCnt = 0;
for(;;) {
h = br.readLine();
if(h == null) {break;}
lineCnt ++;
}
br.close();
is.close();


InputStream is2 = new FileInputStream("URL.dat");
BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));
String h2[] = new String[lineCnt];
for(int h2Cnt=0; h2Cnt<lineCnt; h2Cnt++) {
h2[h2Cnt] = br2.readLine();
}
br2.close();
is2.close();


int setLoop = 3;
int loop = 0;
int count = 0;
Kaiseki2 run[] = new Kaiseki2[lineCnt];
for(int cnt=0; cnt<lineCnt; cnt++) {
run[cnt] = new Kaiseki2(h2[cnt]);
run[cnt].start();
loop++;
if(loop == setLoop){
count = loop + count;
int loopJoin = 0;
loopJoin = cnt + 1 - setLoop;
for(int i=1; i<=setLoop; i++){
run[loopJoin].join();
loopJoin++;
loop=0;
}
System.out.println("Test() "+": "+count);
}
}


int reJoin = lineCnt%setLoop;
int reloop = lineCnt - reJoin;
for(int i=1; i<=reJoin; i++){
run[reloop].join();
reloop++;
}
System.out.println("Test(Finish) "+": "+reloop);

}catch(Exception ex){System.out.println("エラー:Test()");
System.out.println(ex.getMessage());
}
}
}




class Kaiseki2 extends Thread {
private String h = null;

Kaiseki2(String str) {
this.h = str;
}

public void run() {

int LOOP_MAX = 10;
int loopcnt = 0;
try {
OutputStream os = new FileOutputStream("出力.txt",true);
BufferedWriter fr = new BufferedWriter(new OutputStreamWriter(os));
URL url = new URL(h);
while(loopcnt < LOOP_MAX){
try{
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(),"JISAutoDetect"));
for (;;) {
String i = in.readLine();
if( i == null) {break;}

if(i.indexOf("http")!=-1){
fr.write(i.indexOf("http")+"\n");
}
}
in.close();
break;

}catch(Exception e){
loopcnt ++;
System.out.println(url);
System.out.println(loopcnt);
System.out.println("30秒休憩");
System.out.println(e.getMessage());
Thread.sleep(30000);
}
}
fr.close();
os.close();
}catch(Exception ex){System.out.println("エラー:Kaiseki2()");System.out.println(ex.getMessage());}
}
}

補足日時:2004/11/08 19:37
    • good
    • 0
この回答へのお礼

お礼欄で申し訳ありませんが、回答についての質問です。

>>良く分からない部位<<
出力ファイル「出力.txt」は各スレッドで使うため、動作が保証されないと思います。
もし、全てのスレッドが同じファイルに書き込みをしたいのなら、ちょっと仕掛けが必要です。出力ファイルアクセス用のクラスを作って、そのオブジェクトをスレッドに渡します。スレッドから使用される、ファイル書き込み用のメソッドは同期メソッドにしておく必要があります。
>><<

>>動作保証がない点とそのオブジェクトをスレッドに渡すという2点が良く分かりません。
どういう意味でしょうか???

お礼日時:2004/11/08 19:50

>多分、何時間か作動させればそのうち止まるのではないかと考えています。


なにか、良い案はないでしょうか?


プログラムの流れが、うまく制御できていないのだと思いますよ。
想定しているのと違う動きをしていて、エラーが出ているのでしょう。

このプログラムからは、意図が見えにくいので

2.各クラス(Test、Kaiseki2)の役割
3.全体の流れ(概略で結構ですが、説明には各クラスを登場させてください)

を教えてください。

この回答への補足

再三の書き込みいただき本当にありがとうございます。
多分、コードを見れば、お分かりになっていると思いますが、まだ、言語というものに触って間がない状態です。
しかも、独学の時間をかける割にはかどっていない気がします。
こんなひよこに、回答をきありがとうございます!!

■役割について
Testでloopの回数分のURLをURL.datから読み取りだし、スレッドにながしています。そして、loop回数に達すると、最後にKaiseki2に投げたURLの解析を終了するまでjoinを用いて新規のスレッド作成を中断しています。
また、#2にある、Kaiseki2では、実装されているものは、ソースデータより、URLアドレスを抜き出す作業をやっています。煩雑なコードになっているため今回は省略しています。因みに、今回は、Test用に、下記のコードに置き換えていますが、それでも同様のエラーが発生します。
fr.write(i+"\n");

if(i.indexOf("http")!=-1){fr.write(i.indexOf("http")+"\n");}

また、本当なら、
・・・・・・・・・・
if(loop == 2){
count = cnt - 1;
System.out.println("Kaiseki() : " + count);
run[cnt-2].join();
run[cnt-1].join();
loop=0;
}
・・・・・・・・・・
としたいのですがエラーがでて出来ていません。また、一番良いのは、全てのスレッドが終了したら新しくスレッドを開始したいのですが良いコードを思いつくことが出来ていません。

全体の流れは、とりあえず、これで、テキストを作成して、Javaプログラムをとりあえず終了させて、Excelでの処理(手動)にしていますので流れは以上となります。


回答の内容からは外れますが、今の教科書は「やさしいJava第2版」で、メソッドの使い方やJAVA用語の概念がいまいちの見込めないため、習うよりは慣れろということで、様々なホームページより、使えそうなコードをコピーして、自分の必要な物に改造しています。そして、コンパイルエラーがなく、動けばとりあえずは成功というスタンスでやってきています。しかし、コンパイルエラーがなくても、使っているといろいろトラブルが出てきますね。なんとか、Javaを独学したいのですが、こんな調子で良いのでしょうかね?オススメの教科書や、勉強方法がありましたら、教えていただけると幸いです。

補足日時:2004/11/08 17:29
    • good
    • 0

人によってお勧めの本は色々でしょうが、


私は翔泳社の「独習Java」(黄色い本)を最初に読みました。
ソケットについても触れられています。

参考URL:http://www.amazon.co.jp/exec/obidos/ASIN/4798102 …
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!