3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Java Programming Thread Runnable (スレッド)

Last updated at Posted at 2019-05-16

Thread とは

Thread (スレッド) とは 処理を実行する流れの単位 を示す。
パソコン操作についてまとめるなら、

この一連の処理がThread(スレッド)とイメージすると良い。


#シングルスレッド & マルチスレッド
シングルスレッド(左図): 1つの処理だけで終了するスレッド
マルチスレッド(右図): 複数のスレッドが同時に動くスレッド

qiita01 (2).png

このようにイメージできる。
###マルチスレッドの利点
シングルスレッドよりも高速な処理が可能である。

For example)
Microsoft Wordで作業中、同時にスペルチェックが行われていたり,単語数を表示したりしている。
これがマルチスレッドの真骨頂である。


#Thread(スレッド)の基本操作

  • クラスにRunnableインターフェースを実装する。
Runnable.java
class クラス名 implements Runnable{
  public void run(){
    /* 処理を書く */
  }
}
  • Threadのコンストラクタの引数としてRunnableを実装したクラスを渡し、宣言します。
Thread.java
Thread thread = new Thread(クラス型変数);

Thread型のコンストラクタのリファレンスは以下。

Reference-Thread-Constructor(リファレンス)
Thread
public Thread(Runnable target)
  • Threadの起動
    start()メソッドでクラス内のrun()メソッドを実行できます。
ThreadStart.java
thread.start();
  • Threadが終了したかを確認する
    Threadのjoin()メソッドを使用します。
    *今回はThreadが配列で複数あると仮定します。
Join.java
try{
    for(int i=0; i<thread.length; i++){
        thread[i].join();
    }
} catch(InterruptedException ie){
    ie.printStackTrace();
}

###スレッドありとなしの違い
変数sumに1を加算する。
これを1000000000回繰り返すプログラムについてスレッド有無の場合による実行時間の検証。
####スレッドなしの場合

NoThread.java
import java.util.Date;
import java.math.BigInteger;

public class NoThread{
    private static BigInteger N = new BigInteger("1000000000");
    private static BigInteger sum = BigInteger.ZERO;

    public static void main(String[] args){
        long start_time = new Date().getTime();
        calculate();
        long end_time = new Date().getTime();
        output(start_time, end_time);
    }

    public static void calculate(){
        BigInteger i = BigInteger.ZERO;
        while(!i.equals(N)){
            sum = sum.add(BigInteger.ONE);   // sum += i
            i = i.add(BigInteger.ONE);       // i++
        }
    }

    public static void output(long s, long e){
        System.out.println("Sum: "+sum);
        System.out.println("total time: "+(e-s)+"ms");
    }
}

実行結果:
スクリーンショット 2019-06-08 0.06.53.png

Thread数 実行時間
なし 46371 ms
*処理にかかる時間は常に一定ではない。

####スレッドありの場合
今回は実行時の引数にスレッド数を指定します。

ThreadRun.java
import java.math.BigInteger;
import java.util.Date;

public class ThreadRun{
    private static BigInteger N = new BigInteger("1000000000");
    private static BigInteger sum = BigInteger.ZERO;

    public static void main(String[] args){
        int num_threads = Integer.parseInt(args[0]);
        BigInteger range = N.divide(new BigInteger(args[0]));

        ThreadRunnable[] tr = new ThreadRunnable[num_threads];
        Thread[] t = new Thread[num_threads];

        BigInteger low = BigInteger.ONE;
        BigInteger high = low.add(range);
        long start_time = new Date().getTime();

        for(int i=0; i<num_threads-1; i++){
            tr[i] = new ThreadRunnable(low, high);
            t[i] = new Thread(tr[i]);
            t[i].start();

            low = high.add(BigInteger.ONE);
            high = low.add(range);
        }
        tr[num_threads-1] = new ThreadRunnable(low, high);
        t[num_threads-1] = new Thread(tr[num_threads-1]);
        t[num_threads-1].start();

        try{ // check whether threads finished
            for(int i=0; i<num_threads; i++){
                t[i].join();
            }
        } catch(InterruptedException ie){
            ie.printStackTrace();
        }

        for(int i=0; i<num_threads; i++){
            sum = sum.add(tr[i].getSum());
        }
        
        long end_time = new Date().getTime();
        System.out.println("Sum: "+sum);
        System.out.println("total time: "+(end_time-start_time)+"ms");
    }

    protected static class ThreadRunnable implements Runnable{
        private BigInteger sum_temp;
        private BigInteger low, high;
        public ThreadRunnable(BigInteger l, BigInteger h){
            this.low = l;
            this.high = h;
            this.sum_temp = BigInteger.ZERO;
        }

        @Override
        public void run(){
            while(!low.equals(high)){
                sum_temp = sum_temp.add(BigInteger.ONE);  // sum_temp += low
                low = low.add(BigInteger.ONE); // low++;
            }
        }

        public BigInteger getSum(){
            return sum_temp;
        }
    }
}

実行結果:
スクリーンショット 2019-06-08 0.07.05.png
Thread(スレッド)がある場合は、

Thread数 実行時間
8 26840 ms
16 26462 ms
*処理にかかる時間は常に一定ではない。

#####まとめ
スレッドありの場合の方がスレッドなしよりも処理時間が短くなりました。
スレッドを有効活用することで大幅に時間を削減することができる。
だが、スレッドを増やしすぎてしまうと逆に実行時間が多くなるので適切なスレッド数を指定するのが重要。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?