マルチスレッドのプログラムの挙動に疑問があります
- マルチスレッドで動くプログラムで、URLのページのソースを取得する処理を行っています。
- しかし、処理の順序が思ったようにならず、「★★終了★★」という文字列が先に表示されます。
- マルチスレッド内での処理順序を正確に制御するにはどうすれば良いでしょうか。
- ベストアンサー
マルチスレッドのプログラム
マルチスレッドで動くプログラムで下記のようなサンプルを作成したのですが疑問に思うような 挙動をしたので質問させてください。 以下プログラムでは配列に指定したURLのページのソースを取得するプログラムでそれ自体は 動作しました。しかし、コンソール上に最初に「★★終了★★"」という文字列が表示されてから それに続いて目的のソースが表示されるという動作をしました。 私の認識ではex.start()によりExThread内で定義されたrun()の処理がマルチスレッドで実行されて から「★★終了★★"」という文字列が表示されるものと思っていました。 ex.start()が実行されることによりmain()メソッド内の処理が全て非同期の処理になってしまうという ことでしょうか。 また、私が当初想定していたようにExThread内で定義されたrun()の処理がマルチスレッドで 全て実行された後、「★★終了★★"」という文字列が表示されるようにするにはどのように すればよろしいでしょうか。 【サンプル】 public class test { public static void main(String[] args) { String[] listUrls = {"http://www.yahoo.co.jp", "http://www.google.co.jp", "http://httpd.apache.org"}; for(String strUrl : listUrls) { ExThread ex = new ExThread(strUrl); ex.start(); } System.out.println("★★終了★★"); } }
- unko347
- お礼率44% (121/273)
- Java
- 回答数3
- ありがとう数0
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
>その3人集めて一斉に行う処理はマルチスレッドで動作 >させて3人のすべての動作が終了したら「終了」という ご自分で何をすればいいのかわかってるように思えますけど(わかってるというのに気づいていないだけで) 「3人のすべての動作が終了したら」というのは「3人のすべての動作が終了するのを待って「終了」」という事じゃないですか? 質問のプログラムに「終了するのを待つ」というのはどこにあります?
その他の回答 (2)
- maiko0318
- ベストアンサー率21% (1483/6970)
>3人のすべての動作が終了したら「終了」という >文字列を表示させたいと考えています。 run()が終わったら何か情報を返すようにすれば? で、それまで待つようにする。
- maiko0318
- ベストアンサー率21% (1483/6970)
startは処理の開始です。 3人を集めて「やれ」と指令したに過ぎませんので、 当然のごとく、終了を待ってなどいないのです。 「やれ」と指令するとすぐにSystem.out.println("★★終了★★");を行います。 処理を待っていたんではマルチスレッドにはならないでしょ?
補足
ご回答ありがとうございます。 その3人集めて一斉に行う処理はマルチスレッドで動作 させて3人のすべての動作が終了したら「終了」という 文字列を表示させたいと考えています。
関連するQ&A
- HTMLをマルチスレッド通信で取得する方法
HTMLをマルチスレッドで通信して取得するソースを書いてみたのですが 動くことは動くのですが本当に以下ソースでできているのでしょうか。 やりたいこととしてはString[]配列に記述した3つのサイトに同時にアクセスしてHTMLを 取得するという処理を行いたいです。 run()メソッドの中身にマルチスレッドでやりたい処理を書けば上記の望みは叶えられるもの なのでしょうか。 package multiThreadTest; public class test { public static void main(String[] args) { String[] listUrls = {"http://www.yahoo.co.jp", "http://www.google.co.jp", "http://httpd.apache.org"}; ExThread ex = new ExThread(listUrls); ex.run(); } } public class ExThread { private String[] listUrls; ExThread(String[] listUrls) { this.listUrls = listUrls; } public void run() { for(String strUrl : listUrls) { String strHtml = Getter.getHtml(strUrl); //HTMLを取得する処理 System.out.println(strHtml); } } }
- ベストアンサー
- Java
- マルチスレッドについて
現在”猫でもできる”の87、88章を学んでおります。 まず87章でマルチスレッドの根本的なやり方を学びましたが、いきなり疑問が浮かびました。 _beginthread関数によりスレッドをスタートさせ、この関数で登録した関数内で_endthread関数を実行し終了させていることは分かります。 しかし_beginthread関数で登録した関数に引数を渡す処理がどの部分で行われているのかわかりません。 登録する関数はvoid型で引数はvoid*型でなければいけないことは分かったのですが、プログラムのどこを見てもこの登録した関数に引数を渡す処理が行われていません。 その辺の動作の説明を分かる方でいいのでよろしくお願いします。 そして88章では排他制御のマルチスレッドを行うプログラムの製作を行っているのですが、ちょっとした疑問が浮かびました。 EnterCriticalSection関数、LeaveCriticalSection関数ではさまれたプログラムは排他制御され他からアクセスされない。 この関数はこんな理解で良いんですかね? この理解で行くと、88章で説明していきますが、子ウィンドウを2つ作成しそれぞれのプロシージャ内で排他制御された関数をスレッドとしてスタートしています。 この2つのスレッドの動作についてですが、互いに排他制御関数が記述されているため、動作としてはまず左の子ウィンドウのスレッドが処理されている場合、右の子ウィンドウのスレッドは停止している。そして左の子ウィンドウのスレッドの排他制御が解放されたときに、右の子ウィンドウのスレッドが開始する。 そしてあるとき左の子ウィンドウのクライアントウィンドウ内で右クリックされた場合、その時点で排他制御されたスレッドが終了するのを待ち、終了したらcountを+1する。 こんな動作が行なわれていると理解してよいのでしょうか?
- ベストアンサー
- C・C++・C#
- マルチスレッドについて。
今、大きな配列を元に処理を行うプログラムを作成しています。 シングルスレッドでも十分速度を向上するようチューニングに成功しましたが、マルチスレッド化をすればさらに速度を向上させることができるだろうと考え、先日マルチスレッドかに成功しました。 しかし・・・奇妙な現象が起こりました。 マルチスレッドで性能を引き出すには、排他制御はないほうが良いと考え、メモリは食いますがスレッドに与える入力情報(大きな配列)を2つ用意し、排他制御なしの2スレッドを実行できるようにしました。しかしやはりメモリを消費しすぎてしまうため、配列にアクセスする部分のみ排他制御を行うようクリティカルセクションを設定し入力情報を2スレッドで共有して処理を行うよう組み替えました。 結果、やはり排他制御なしの場合よりはるかにスピードダウンしてしまい、シングルスレッドより少し早い処理時間で終了してしまいました。 余りにも悔しいため、ちょっと危険な実験だとは思いましたが、入力情報を2つのスレッドで共有しているにもかかわらず、排他制御の部分、つまりクリティカルセクションを取り除いて実行してみようと考えました。予想としては同時にアクセスし衝突が起きてエラーで停止してしまうと考えましたが・・・・・・ 結果なぜかエラーなく処理をし続け、普通に終了してしまいました。 これはなぜでしょう? 偶然にも共有情報に同時にアクセスすることがなかったためでしょうか?
- ベストアンサー
- C・C++・C#
- C# マルチスレッドにおける例外処理
下記のようなデリゲートを利用したマルチスレッドのプログラムを組みました。 しかし、マルチスレッド内で例外がおきても、正常にプログラムが終了してしまいます。 (try-catchでも例外を捕捉できません) マルチスレッドプログラムにおいて、例外を捕捉するにはどうすれば、いいのでしょうか? using System; using System.Threading; class Class1 { delegate void delg(); public static void Main() { delg d = new delg(multi); d.BeginInvoke(new AsyncCallback(call), null); //マルチスレッド開始 System.Threading.Thread.Sleep(500); //マルチスレッドで例外を強制的に投げているので、 //ここまでたどり着く前にアプリケーションが落ちるはず。 //しかし、実際には正常終了。 Console.WriteLine("メインメソッド 正常終了"); } public static void multi() { Console.WriteLine("マルチスレッドで実行中"); throw new Exception(); //例外を強制的に投げる。 } public static void call(IAsyncResult ar) { Console.WriteLine("コールバックメソッド実行"); } }
- ベストアンサー
- C・C++・C#
- JAVAのマルチスレッドの共有変数についての質問
JAVAのマルチスレッドの共有変数についての質問です。 スレッドを2つ作ってその2つのスレッド共有の配列を作りたいのですがどうすれば良いのでしょうか。 コードは以下のとおりです。 public class testes extends Thread { int n; int a[]={10,10}; public testes(int n){ this.n = n; } public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ testes t1 = new testes(0); testes t2 = new testes(1); t1.start(); t2.start(); } public void run(){ a[n] =n; System.out.println(a[0]+","+a[1]); } } 実行すると(0,10)もしくは(10,1)が表示されます。 このとき(0,1)と表示するにはどうすれば良いのでしょうか。
- 締切済み
- Java
- マルチスレッド化。
今とても大きな配列を使用し、長時間処理をするプログラムを組んでいます。元々処理時間に1時間を要するプログラムを2分で処理を完了するまでに仕上げました。 しかし、探究心はおさまらずもう少し高速化に挑みたいと考えています。 過去に「猫でもわかる」のSDK第1章と2章を学び、マルチスレッドのプログラムをSDKで組んだことがあります。それを利用してマルチスレッド化を実現したいと考えています。 言語はCでVisualStudio2005を使用しています。 *疑問1 SDKの場合WinMain関数とプロシージャからの実行で_beginthread関数を記述すれば処理が開始されます。 Cでもmain関数内に記述すれば、SDKと同様に処理できるのでしょうか? *疑問2 _beginthread関数の引数に関してです。 第1引数にvoid型のスレッド関数、第2引数に0?、そして第3引数にはスレッド関数に渡すデータの引数を記述すると把握しているのですが、渡したいデータは複数あり、***型と**型、それに変数を数個とスレッド関数に渡したいデータだらけなのですが、どのように記述すればよいでしょう? *疑問3 2つのスレッドを作成しようと考えていますが、その2つのスレッドで1つの大きな配列を共有して処理したいと考えています。 そのため、スレッド間の同期が必要になるわけですが同期の種類にもクリティカルセクションやミューテックス、イベントと豊富でどれを使用すれば良いのか迷ってしまいます。厳密に同期を取り処理をするにはイベントが一番良いと考えています。 これらの疑問に答えられる方はアドバイスをよろしくお願いします。
- ベストアンサー
- C・C++・C#
- スレッドに関して(高橋麻奈の本)
はじめまして。 現在、高橋麻奈の「やさしいJAVA」を読んで勉強している初心者です。 スレッドに関する記述(P.466)で分からない点があります。下記のコードを実行すると、 mainの処理をしています。 mainの処理をしています。 1号車の処理をしています。 mainの処理をしています。 ・ ・ の文字がアトランダムに並ぶとの事ですが、実行すると、 mainの処理をしています。 mainの処理をしています。 mainの処理をしています。 mainの処理をしています。 mainの処理をしています。 1号車の処理をしています。 1号車の処理をしています。 1号車の処理をしています。 1号車の処理をしています。 1号車の処理をしています。 と、アトランダムにならずに表示されてしまいますが、何故でしょうか?下記にコードを載せておきます。長くなって、申し訳有りません。 ---コード----------- class Car extends Thread { private String name; public Car(String nm) { name = nm; } public void run() { for(int i=0; i<5; i++){ System.out.println(name+"の処理をしています。"); } } } class Sample1 { public static void main(String args[]) { Car car1 = new Car("1号車"); car1.start(); for(int i=0; i<5; i++){ System.out.println("main()の処理をしています。"); } } }
- ベストアンサー
- Java
- コマンドプロンプトで
こんにちは。質問させてください。 いままでPHPをWEBブラウザの処理をMainに作成してきました。 簡単な文字列を整形するプログラムを作りました。 これは画面(ブラウザ)に表示するのではないので コマンドプロンプトで実行したいのですが、 単に c:\work>sample.php と実行すると、 エディタが開いてsample.phpの内容を表示するだけに なってしまい、特に処理が行われていません。 どのようにすればコマンドプロンプトから実行できるのでしょうか? C言語のように実行ファイルをコマンドプロンプトから 実行して処理させるようにしたいのですが・・・・ 質問自体が大きな間違いでしたらすみません。 どうかよろしくお願いいたします。
- 締切済み
- PHP
- フレーム分割のソース表示プログラムについて
以前次のようなプログラムを作ったのですが、これはURLを入力するとブラウザのソースを表示するものなので、フレームによって分割されたページのソースはすべて表示させることができません。このプログラムに何か追加して分割されていてもソースが表示できるようにしたいのですが。新たにコマンドを作ってやるしかないのでしょうか?何かアドバイスお願いします。 Private Sub Command1_Click() Dim strUrl As String Dim strBuf As String Command1.Enabled = False strUrl = InputBox("URLを入力して下さい.") If (Len(strUrl) = 0) Then Exit Sub End If Command1.Enabled = True strBuf = Inet1.OpenURL(strUrl) Form2.Show Form2.Text1.Text = strBuf End Sub Function Getsource() As String Dim strBuf As String Dim strUrl As String Dim strUrl2 As String strBuf = Inet1.OpenURL(strUrl) 'ファイル内容を取得 strUrl2 = InStr(strBuf, "frame src=") If strUrl2 > 0 Then strUrl3 = Mid(strBuf, strUrl2, 100) strUrl4 = Mid(strUrl3, 1, l) Getsource = strBuf End Function
- ベストアンサー
- Visual Basic
- プログラム実行中にプログラムを書き換えるには?
実行中のプログラムの中でそのプログラムの一部を書き換えて保存するにはどうすればいいですか? 例えば次のようなプログラムの場合、このプログラムの中でTEXT("最初の文字列");の部分の文字列を別な文字列に変更しプログラムを更新したいです。 (プログラム終了後にもう一度実行すると「moji[20]=」の部分は前回実行時に書き換えた文字列が代入されているようにしたい) #include<windows.h> int WINAPI WinMain(HINSTANCE hinst,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int ncmdshow){ TCHAR moji[20]=TEXT("最初の文字列"); MessageBox(NULL,moji,TEXT("文字列表示"),MB_OK); return 0; } --- 実行環境 --- Microsoft Visual C++ 2010 Express WIN32 ユニコードビルド C言語
- ベストアンサー
- C・C++・C#
補足
「待つ」という処理が必要だったんですね。 調べてみたらjoin()というメソッドでスレッドの待機が できるとのことだったので以下のようにしてみたところうまくいきました。ありがとうございました。 public static void main(String[] args) throws InterruptedException { String[] listUrls = {"http://www.yahoo.co.jp", "http://www.google.co.jp", "http://httpd.apache.org"}; ExThread[] threads = new ExThread[listUrls.length]; for(int i=0; i<listUrls.length; i++) { threads[i] = new ExThread(listUrls[i]); threads[i].start(); } // 全てのスレッドが終了するのを待つ for(int i=0; i<listUrls.length; i++) { threads[i].join(); } System.out.println("★★終了★★"); }