見出し画像

【Javaお勉強日記】マルチスレッド処理についてざっくり

重たい処理を同時並行で複数処理させる時に便利なマルチスレッドの書き方を色々わーっと。

あんまり凝りすぎるとコールバック地獄が見えてくるので用法用量を守って使った方がよさそう。

package source_and_data.ch01.src.my_samples;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class MultiThreadTest {

public static void main (String args[]) throws Exception{
       // スレッドを使う度に立てる方法
       Thread t1 = new Thread( () -> {Calc c1 = new Calc(5); c1.doit();} );
       Thread t2 = new Thread( () -> {Calc c2 = new Calc(10); c2.doit();} );
       Thread t3 = new Thread( () -> {Calc c3 = new Calc(15); c3.doit();} );
       t1.start();
       t2.start();
       t3.start();
       
       // 固定数のスレッドをプールしておいてそこから使う方法
       ExecutorService es = Executors.newFixedThreadPool(5);
       es.execute( () -> {Calc c4 = new Calc(20); c4.doit();} );
       es.execute( () -> {Calc c5 = new Calc(25); c5.doit();} );
       es.execute( () -> {Calc c6 = new Calc(30); c6.doit();} );
       es.shutdown(); // スレッドプールは不要になったらシャットダウンする
       
       
       // 前の処理が終わったら次の処理が始まるタイプの非同期処理をする
       // 基本の非同期処理を起動する
       CompletableFuture<Integer> future 
           = CompletableFuture.supplyAsync(() -> {
               CalcReturn calcreturn1 = new CalcReturn(40);
               return calcreturn1.doit();
           });
       // 結果を受け取る
       int message = future.get(); // get()を使うと待ち合わせが発生する
       System.out.println(message);
       
       // メソッドチェーンでできるだけgetを使わず処理をする
       CompletableFuture<Void> future2
           = CompletableFuture
               .supplyAsync(() -> "ここで何かの複雑な処理をする")
               .thenApply(result1 -> result1 + "-> の結果にさらに処理を加える")
               .thenAccept(result2 -> System.out.println(result2 + "-> の結果を使って続きの処理をする"))
               .thenRun(() -> System.out.println("何も受け取らず何も返さない処理も挟める"))
               .orTimeout(1, TimeUnit.SECONDS) // タイムアウトを設定する
               .whenComplete((returnVal, errorObj) -> { // 後処理を加えてエラー対策をする
                   if(errorObj == null){System.out.println("成功したとき");}
                   else{System.out.println("エラーのとき");}
               });
       
   }
}
// Calc.java
public class Calc{
   private int n;
   public Calc(int n){
       this.n = n;
   }
   public void doit(){
       System.out.println("start::" + this.n);
       int result = this.n;
       for(int c=0; c < 100; c++){
           result = result + c;
       }
       System.out.println("end::" + this.n + "->" + result);
   }
}
// CalcReturn.java 戻り値があるタイプの処理
public class CalcReturn{
   private int n;
   public CalcReturn(int n){
       this.n = n;
   }
   public int doit(){
       System.out.println("start::" + this.n);
       int result = this.n;
       for(int c=0; c < 100; c++){
           result = result + c;
       }
       System.out.println("end::" + this.n + "->" + result);
       return result;
   }
}

ちょっと時間がないので、今回はざっくり防備録だけ。

この記事が気に入ったらサポートをしてみませんか?