質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

802閲覧

乱数を格納した配列を昇順にして表示したい

tuka

総合スコア13

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2022/06/20 09:14

編集2022/06/21 06:02

以下のようなコードを書いて実行したのですが、乱数がばらばらに表示してしまいます。配列に格納して昇順に出力したいのですが、どなたか解決方法教えてください。

該当コード

java

1import java.util.Calendar; 2import java.text.SimpleDateFormat; 3import java.util.Date; 4import java.util.Arrays; 5import java.util.Random; 6 7class ThreadLearnss extends Thread { 8 public void run() { 9 for (int i = 0; i < 30; i++) { 10 } 11 } 12} 13 14class mains { 15 public static void main(String[] args) { 16 for (int h = 0; h < 30; h++) { 17 Thread[] th = new Thread[30]; 18 Date date = new Date(); 19 SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); 20 Calendar calendar = Calendar.getInstance(); 21 22 for (Thread s : th) { 23 s.start(); 24 int[] nums; 25 for (int i = 0; i < 30; i++) { 26 th[i] = new Thread(); 27 calendar.setTime(date); 28 nums = new Random().ints(30, 2, 11).toArray(); 29 Date d1 = calendar.getTime(); 30 calendar.add(Calendar.SECOND, nums[i]); 31 Arrays.sort(nums); 32 33 System.out.printf("%d %s %s %s %d %s %s\n", s.getId(), "start", sdf.format(date), "wait", 34 nums[i], sdf.format(d1), "end"); 35 } 36 37 } 38 39 for (Thread t : th) { 40 try { 41 t.join(); 42 } catch (InterruptedException e) { 43 System.out.println(e); 44 } finally { 45 System.out.printf("%s", "program end"); 46 } 47 } 48 } 49 } 50} 51

出力

java

115 start 08:25:53 wait 5 08:25:58 end 216 start 08:25:53 wait 3 08:25:56 end 317 start 08:25:53 wait 5 08:25:58 end 418 start 08:25:53 wait 9 08:26:02 end 519 start 08:25:53 wait 7 08:26:00 end 620 start 08:25:53 wait 8 08:26:01 end 721 start 08:25:53 wait 4 08:25:57 end 822 start 08:25:53 wait 7 08:26:00 end 923 start 08:25:53 wait 6 08:25:59 end 1024 start 08:25:53 wait 2 08:25:55 end 1125 start 08:25:53 wait 2 08:25:55 end 1226 start 08:25:53 wait 4 08:25:57 end 1327 start 08:25:53 wait 2 08:25:55 end 1428 start 08:25:53 wait 7 08:26:00 end 1529 start 08:25:53 wait 6 08:25:59 end 1630 start 08:25:53 wait 7 08:26:00 end 1731 start 08:25:53 wait 10 08:26:03 end 1832 start 08:25:53 wait 9 08:26:02 end 1933 start 08:25:53 wait 2 08:25:55 end 2034 start 08:25:53 wait 6 08:25:59 end 2135 start 08:25:53 wait 9 08:26:02 end 2236 start 08:25:53 wait 7 08:26:00 end 2337 start 08:25:53 wait 10 08:26:03 end 2438 start 08:25:53 wait 7 08:26:00 end 2539 start 08:25:53 wait 4 08:25:57 end 2640 start 08:25:53 wait 8 08:26:01 end 2741 start 08:25:53 wait 4 08:25:57 end 2842 start 08:25:53 wait 9 08:26:02 end 2943 start 08:25:53 wait 3 08:25:56 end 3044 start 08:25:53 wait 8 08:26:01 end 31program end

試したこと

Arrays.sort(nums);とSystem.out.printfをfor文の外に出した。当然ですがSystem.out.printfのnums[i]がエラーになる

追記

java

1import java.util.Calendar; 2import java.text.SimpleDateFormat; 3import java.util.Date; 4import java.util.Arrays; 5import java.util.Random; 6 7class mains { 8 public static void main(String[] args) { 9 Thread[] th = new Thread[30]; 10 Date date = new Date(); 11 SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); 12 Calendar calendar = Calendar.getInstance(); 13 int[] nums = new Random().ints(30, 2, 11).toArray(); 14 Arrays.sort(nums); 15 for (int i = 0; i < 30; i++) { 16 th[i] = new Thread(); 17 th[i].start(); 18 calendar.setTime(date); 19 Date d1 = calendar.getTime(); 20 calendar.add(Calendar.SECOND, nums[i]); 21 22 System.out.printf("%d %s %s %s %d %s %s\n", th[i].getId(), "start", sdf.format(date), "wait", 23 nums[i], sdf.format(d1), "end"); 24 } 25 26 for (Thread t : th) { 27 try { 28 t.join(); 29 } catch (InterruptedException e) { 30 System.out.println(e); 31 } finally { 32 System.out.printf("%s", "program end"); 33 } 34 } 35 } 36} 37

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

int32_t

2022/06/20 09:31

これはどういう意図のコードなんでしょうか。なぜ Thread を使っているのでしょうか。日本語で説明していただけませんか? 「Arrays.sort(nums);」は 27,000 回実行されるように見えますが、これは意図どおりですか?
dodox86

2022/06/20 10:53

何となくコードを書いて動かないと嘆き、質問するのは止めましょう。やりたいこと、ご要望は分からなくもないですが、コードが意図不明です。
tuka

2022/06/20 14:22

すみません、説明不足でした。Threadを30個作って,各スレッドではスレッドのIDを取得,開始時刻を取得,乱数で2から10秒待ち,終了時刻を取得し,スレッドID,開始時刻,待ち秒数,終了時刻を表⽰させるプログラムを作ろうとしているのですが、プログラムの一部しか提示していなかったため、全て提示するように編集します。
dodox86

2022/06/20 16:49

乱数の配列のソート云々の前に、ThreadLearnssクラスのスレッドの開始や終了待ちの処理がメチャクチャに見えます。その辺りはデバッグ済みで、意図通り動作しているのでしょうか。
jimbe

2022/06/20 18:17 編集

s.start() で止まってそうに見えますが…。 Thread オブジェクトは放置されています。 何もしてない ThreadLearnss は使われていませんし。 乱数で待つってカレンダーに足している部分のことでしょうか。
int32_t

2022/06/20 23:20

> s.start() で止まってそうに見えますが…。 ぬるぽですよねえ。
tuka

2022/06/20 23:24

一応デバック済みで大方意図通りの動作はしています。 乱数で待ってカレンダーに足している部分のことですが、乱数表示を昇順に出力したいです。 ThreadLearnssでスレッドID取得させるなど、活用したほうがプログラムとして正しい書き方になりますよね。 Threadオブジェクトを有効に使うにはどうしたらよいでしょうか?
guest

回答2

0

「Threadを30個作って,各スレッドではスレッドのIDを取得,開始時刻を取得,乱数で2から10秒待ち,終了時刻を取得し,スレッドID,開始時刻,待ち秒数,終了時刻を表⽰させるプログラム」という仕様からは以下のような動作と想像します。(30個という数はテストには意味が無いので10個にしてますが。)
しかし作られたコードはそうならず、なんとか動かした結果何かの数字は出てきたので『とりあえず並び替えればそれっぽいのでは』ということで本件に至ったのではないでしょうか。

ちなみに、現在ご提示されているコードをコピペして実行するとやはり s.start() で NullPointerException が発生しますので、tukaさんのお手元で発生していなければ、コードが異なっているものと思います。(もしくは、動かしていると思っているコードと実際に動作しているコードが違う?)

java

1import java.text.SimpleDateFormat; 2import java.util.Date; 3import java.util.Random; 4 5class Main { 6 public static void main(String[] args) { 7 Random random = new Random(); 8 Thread[] th = new Thread[10]; 9 10 for (int i=0; i<th.length; i++) { 11 final int wait = random.nextInt(9) + 2; //[s] 12 th[i] = new Thread(() -> { 13 long id = Thread.currentThread().getId(); 14 Date start = new Date(); 15 try { 16 Thread.sleep(wait * 1000L); 17 } catch(InterruptedException e) { 18 e.printStackTrace(); 19 } 20 Date end = new Date(); 21 print(id, start, wait, end); 22 }); 23 th[i].start(); 24 } 25 26 for (Thread t : th) { 27 try { 28 t.join(); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 } 33 34 System.out.println("program end"); 35 } 36 37 private static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); 38 39 private static synchronized void print(long id, Date start, long wait, Date end) { 40 System.out.println(new StringBuilder() 41 .append(id) 42 .append(" start=").append(sdf.format(start)) 43 .append(" wait=").append(wait) 44 .append(" end=").append(sdf.format(end)) 45 .toString()); 46 } 47}

plain

119 start=13:30:46 wait=2 end=13:30:48 221 start=13:30:46 wait=2 end=13:30:48 312 start=13:30:46 wait=3 end=13:30:49 413 start=13:30:46 wait=5 end=13:30:51 520 start=13:30:46 wait=6 end=13:30:52 615 start=13:30:46 wait=6 end=13:30:52 716 start=13:30:46 wait=9 end=13:30:55 817 start=13:30:46 wait=10 end=13:30:56 918 start=13:30:46 wait=10 end=13:30:56 1014 start=13:30:46 wait=10 end=13:30:56 11program end

投稿2022/06/21 03:39

編集2022/06/21 04:32
jimbe

総合スコア12648

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tuka

2022/06/21 04:11

回答ありがとうございます。参考にさせていただきます。 2つほど質問があります。 ・待ち時間を2や5などの一の位だけで表示させるにはどのようなコードの変更が必要ですか? ・すべての処理が終わった後に終わりを告げる文字列の追加はfinallyで追加すれば良いですか?
jimbe

2022/06/21 04:29

回答のコードを書いた時点で待ち時間の精度が秒なのか分からなかったので、ミリ秒の精度にしています。 秒の精度で良ければ秒で処理するようにすれば良いでしょう。 プログラムの全処理が終わったら表示するのであれば、 main メソッドの最後に追加するだけです。
tuka

2022/06/21 05:38

すみません、経験が浅くて秒で処理する方法が分かりません。jimbeさんのコードをコピペさせていただき、変数waitをint型にして範囲を2から10にしましたが、endでstartの時と時間表示が変わりませんでした。 どのように処理すれば良いのかアドバイスいただけませんか?
jimbe

2022/06/21 05:53

回答のコードを変更してありますので、変更前からコピペされていましたら再度コピペしていただけますか。お手数お掛けしましてすいません。
tuka

2022/06/21 08:38

こちらこそお手数お掛けしました。大変参考になりました、ありがとうございます。
guest

0

ベストアンサー

何をするためのコードなのか依然として理解できませんが、「乱数を格納した配列を昇順にして表示したい」ということであれば、以下のようにする必要があります。

java

1 // 30個の乱数からint配列を生成 2 int[] nums = new Random().ints(30, 2, 11).toArray(); 3 // それをソート 4 Arrays.sort(nums); 5 // それを順番に表示 6 for (int j = 0; j < nums.length; ++j) 7 System.out.printf("nums[%d] = %d\n", j, nums[j]);

ただし、これが本当に質問者さんがやりたいことなのかは確信がもてません。
質問文のコードでは乱数30個の生成とそのソートがメインスレッドで 27,000 回実行されます。(hのループ * thのループ * iのループ)


追記:
やりたいことはなんとなく理解できた気がします。「個々のスレッドに乱数を割り当て、そのスレッドの情報を乱数順に表示したい」ということなのでしょう。以下のような構成にするといいんじゃないでしょうか。

java

1 int[] nums = new Random().ints(30, 2, 11).toArray(); 2 Arrays.sort(nums); 3 for (int i = 0; i < 30; i++) { 4 th[i] = new Thread(); 5 th[i].start(); 6 calendar.setTime(date); 7 calendar.add(Calendar.SECOND, nums[i]); 8 Date d1 = calendar.getTime(); 9 10 System.out.printf("%d %s %s %s %d %s %s\n", th[i].getId(), "start", sdf.format(date), "wait", 11 nums[i], sdf.format(d1), "end"); 12 }

投稿2022/06/20 23:19

編集2022/06/21 04:58
int32_t

総合スコア20884

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tuka

2022/06/21 03:33

回答いただきありがとうございます。ここで言う乱数順とは小さい順のことでしょうか。そうでしたら乱数順で表示したいです。 回答いただいたプログラムを参考にさせていただき、実装したところ乱数の並びがばらばらのままで乱数順になりませんでした。Arrays.sort(nums);する前にforでその都度乱数をnums配列に格納し、そのあとArrays.sort(nums);した方が良いのでしょうか? 経験が浅く、書き方が分からないので、もう少し付き合っていただけると助かります。
int32_t

2022/06/21 03:37

> ここで言う乱数順とは小さい順 はい。 コードを見ないと助言できないので、現在のコードを(元のコードを消さずに)質問文に追記してください。
tuka

2022/06/21 03:50

分かりました
int32_t

2022/06/21 04:03 編集

for (Thread s : th) { s.start(); が不要だと思います。 あと一番外側の h のループも必要ですか? 30個ではなく900個のスレッド情報の表示をソートしたいという話だったりします?
tuka

2022/06/21 04:24

> あと一番外側の h のループも必要ですか? 30個ではなく900個のスレッド情報の表示をソートしたいという話だったりします? 30個のスレッド表示ですね。 for (Thread s : th) { s.start();とhのループ除いて実行しましたが依然として結果は変わらず。やはり全体の書き方が間違っているのでしょうか。 アドバイスいただき、修正したコードを追記に更新しておきます。
int32_t

2022/06/21 04:58

System.out.printf() の直前の「for (Thread s : th) {」は不要です。System.out.printf() で表示するのは s.getId() ではなく th[i].getId() ですね。回答の不備ですすみません。
tuka

2022/06/21 06:01

再度修正しましたが結果は変わらずでした。配列に格納し終えてからArrays.sort(nums);すべきですかね。 アドバイスいただき、修正したコードを追記に更新します。
int32_t

2022/06/21 06:06

現状のコードでどういう出力になりますか?
tuka

2022/06/21 07:14

質問の出力結果と全く同じ出力です
int32_t

2022/06/21 07:21

> 質問の出力結果と全く同じ出力です それはおかしいですね。更新しているソースと実行している *.class が一致してないのかもしれません。
tuka

2022/06/21 23:35

連絡遅れてすみません。class一致していませんでした。変更により乱数が昇順で出力することができました、ありがとうございました。 最初に回答してくれたのと、私の作っていたプログラムの修正をしてくれたのでベストアンサーにさせていただきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問