kok202
자바의 병렬 처리 발전사

2019. 5. 3. 14:45[개발] 기록

구구단 병렬 처리

1. Java 8 이전 : Thread

public class Main{
    public static void main(String[] args) {
        for(int i = 2 ; i < 10 ; i++ ){
            MyThread test = new MyThread(i);
            test.start();
        }
    }
}

@AllArgsConstructor
class MyThread extends Thread {
    private int left = -1;
    public void run(){
        for(int right = 1 ; right < 10 ; right++ ){
            System.out.println(Thread.currentThread().getName() + "\t" + left + " * " + right + " = " + (left * right));
        }
    }
}
Thread-1	3 * 1 = 3
Thread-4	6 * 1 = 6
Thread-1	3 * 2 = 6
Thread-3	5 * 1 = 5
Thread-2	4 * 1 = 4
Thread-0	2 * 1 = 2
Thread-6	8 * 1 = 8
Thread-2	4 * 2 = 8
Thread-3	5 * 2 = 10
Thread-1	3 * 3 = 9
Thread-5	7 * 1 = 7
Thread-4	6 * 2 = 12
Thread-5	7 * 2 = 14
Thread-1	3 * 4 = 12
Thread-3	5 * 3 = 15
Thread-2	4 * 3 = 12
Thread-6	8 * 2 = 16
Thread-7	9 * 1 = 9
Thread-0	2 * 2 = 4
Thread-7	9 * 2 = 18
Thread-6	8 * 3 = 24
Thread-2	4 * 4 = 16
Thread-3	5 * 4 = 20
Thread-1	3 * 5 = 15
Thread-5	7 * 3 = 21
Thread-4	6 * 3 = 18
Thread-5	7 * 4 = 28
Thread-5	7 * 5 = 35
Thread-5	7 * 6 = 42
Thread-1	3 * 6 = 18
Thread-3	5 * 5 = 25
Thread-2	4 * 5 = 20
Thread-6	8 * 4 = 32
Thread-7	9 * 3 = 27
Thread-0	2 * 3 = 6
Thread-7	9 * 4 = 36
Thread-6	8 * 5 = 40
Thread-2	4 * 6 = 24
Thread-3	5 * 6 = 30
Thread-1	3 * 7 = 21
Thread-5	7 * 7 = 49
Thread-4	6 * 4 = 24
Thread-4	6 * 5 = 30
Thread-4	6 * 6 = 36
Thread-4	6 * 7 = 42
Thread-4	6 * 8 = 48
Thread-4	6 * 9 = 54
Thread-5	7 * 8 = 56
Thread-1	3 * 8 = 24
Thread-3	5 * 7 = 35
Thread-2	4 * 7 = 28
Thread-6	8 * 6 = 48
Thread-6	8 * 7 = 56
Thread-7	9 * 5 = 45
Thread-0	2 * 4 = 8
Thread-7	9 * 6 = 54
Thread-6	8 * 8 = 64
Thread-2	4 * 8 = 32
Thread-3	5 * 8 = 40
Thread-1	3 * 9 = 27
Thread-5	7 * 9 = 63
Thread-3	5 * 9 = 45
Thread-2	4 * 9 = 36
Thread-6	8 * 9 = 72
Thread-7	9 * 7 = 63
Thread-0	2 * 5 = 10
Thread-7	9 * 8 = 72
Thread-7	9 * 9 = 81
Thread-0	2 * 6 = 12
Thread-0	2 * 7 = 14
Thread-0	2 * 8 = 16
Thread-0	2 * 9 = 18

Process finished with exit code 0

 

 

 

 

 

2. Java 7 이전 : ExecutorService

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

public class Main{
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        for(int i = 2 ; i < 10 ; i++ ){
            
            final int left = i;
            executor.submit(new Runnable(){
                @Override
                public void run() {
                    for(int right = 1 ; right < 10 ; right++){
                        System.out.println(Thread.currentThread().getName() + "\t" + left + " * " + right + " = " + (left * right));
                    }
                }
                
            });
        }
        executor.shutdown();
    }
}
pool-1-thread-1	2 * 1 = 2
pool-1-thread-3	4 * 1 = 4
pool-1-thread-2	3 * 1 = 3
pool-1-thread-3	4 * 2 = 8
pool-1-thread-4	5 * 1 = 5
pool-1-thread-1	2 * 2 = 4
pool-1-thread-1	2 * 3 = 6
pool-1-thread-4	5 * 2 = 10
pool-1-thread-3	4 * 3 = 12
pool-1-thread-5	6 * 1 = 6
pool-1-thread-2	3 * 2 = 6
pool-1-thread-5	6 * 2 = 12
pool-1-thread-3	4 * 4 = 16
pool-1-thread-4	5 * 3 = 15
pool-1-thread-1	2 * 4 = 8
pool-1-thread-4	5 * 4 = 20
pool-1-thread-3	4 * 5 = 20
pool-1-thread-5	6 * 3 = 18
pool-1-thread-2	3 * 3 = 9
pool-1-thread-5	6 * 4 = 24
pool-1-thread-3	4 * 6 = 24
pool-1-thread-3	4 * 7 = 28
pool-1-thread-3	4 * 8 = 32
pool-1-thread-3	4 * 9 = 36
pool-1-thread-4	5 * 5 = 25
pool-1-thread-1	2 * 5 = 10
pool-1-thread-4	5 * 6 = 30
pool-1-thread-3	7 * 1 = 7
pool-1-thread-5	6 * 5 = 30
pool-1-thread-2	3 * 4 = 12
pool-1-thread-5	6 * 6 = 36
pool-1-thread-3	7 * 2 = 14
pool-1-thread-4	5 * 7 = 35
pool-1-thread-4	5 * 8 = 40
pool-1-thread-1	2 * 6 = 12
pool-1-thread-4	5 * 9 = 45
pool-1-thread-3	7 * 3 = 21
pool-1-thread-5	6 * 7 = 42
pool-1-thread-5	6 * 8 = 48
pool-1-thread-5	6 * 9 = 54
pool-1-thread-2	3 * 5 = 15
pool-1-thread-5	9 * 1 = 9
pool-1-thread-3	7 * 4 = 28
pool-1-thread-3	7 * 5 = 35
pool-1-thread-4	8 * 1 = 8
pool-1-thread-1	2 * 7 = 14
pool-1-thread-4	8 * 2 = 16
pool-1-thread-3	7 * 6 = 42
pool-1-thread-5	9 * 2 = 18
pool-1-thread-2	3 * 6 = 18
pool-1-thread-5	9 * 3 = 27
pool-1-thread-3	7 * 7 = 49
pool-1-thread-3	7 * 8 = 56
pool-1-thread-3	7 * 9 = 63
pool-1-thread-4	8 * 3 = 24
pool-1-thread-4	8 * 4 = 32
pool-1-thread-4	8 * 5 = 40
pool-1-thread-4	8 * 6 = 48
pool-1-thread-4	8 * 7 = 56
pool-1-thread-4	8 * 8 = 64
pool-1-thread-4	8 * 9 = 72
pool-1-thread-1	2 * 8 = 16
pool-1-thread-5	9 * 4 = 36
pool-1-thread-2	3 * 7 = 21
pool-1-thread-5	9 * 5 = 45
pool-1-thread-1	2 * 9 = 18
pool-1-thread-5	9 * 6 = 54
pool-1-thread-2	3 * 8 = 24
pool-1-thread-5	9 * 7 = 63
pool-1-thread-2	3 * 9 = 27
pool-1-thread-5	9 * 8 = 72
pool-1-thread-5	9 * 9 = 81

Process finished with exit code 0

 

 

 

 

 

3. 자바 8 이후 : ExecutorService + 람다식

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

public class Main{
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        for(int i = 2 ; i < 10 ; i++ ){

            final int left = i;
            executor.submit(()->{
                for(int right = 1 ; right < 10 ; right++){
                    System.out.println(Thread.currentThread().getName() + "\t" + left + " * " + right + " = " + (left * right));
                }
            });

        }
        executor.shutdown();
    }
}
pool-1-thread-1	2 * 1 = 2
pool-1-thread-3	4 * 1 = 4
pool-1-thread-3	4 * 2 = 8
pool-1-thread-2	3 * 1 = 3
pool-1-thread-5	6 * 1 = 6
pool-1-thread-5	6 * 2 = 12
pool-1-thread-5	6 * 3 = 18
pool-1-thread-2	3 * 2 = 6
pool-1-thread-3	4 * 3 = 12
pool-1-thread-1	2 * 2 = 4
pool-1-thread-4	5 * 1 = 5
pool-1-thread-4	5 * 2 = 10
pool-1-thread-4	5 * 3 = 15
pool-1-thread-4	5 * 4 = 20
pool-1-thread-4	5 * 5 = 25
pool-1-thread-1	2 * 3 = 6
pool-1-thread-3	4 * 4 = 16
pool-1-thread-2	3 * 3 = 9
pool-1-thread-5	6 * 4 = 24
pool-1-thread-5	6 * 5 = 30
pool-1-thread-2	3 * 4 = 12
pool-1-thread-3	4 * 5 = 20
pool-1-thread-1	2 * 4 = 8
pool-1-thread-4	5 * 6 = 30
pool-1-thread-1	2 * 5 = 10
pool-1-thread-1	2 * 6 = 12
pool-1-thread-3	4 * 6 = 24
pool-1-thread-2	3 * 5 = 15
pool-1-thread-5	6 * 6 = 36
pool-1-thread-2	3 * 6 = 18
pool-1-thread-2	3 * 7 = 21
pool-1-thread-2	3 * 8 = 24
pool-1-thread-3	4 * 7 = 28
pool-1-thread-1	2 * 7 = 14
pool-1-thread-1	2 * 8 = 16
pool-1-thread-1	2 * 9 = 18
pool-1-thread-4	5 * 7 = 35
pool-1-thread-3	4 * 8 = 32
pool-1-thread-2	3 * 9 = 27
pool-1-thread-5	6 * 7 = 42
pool-1-thread-2	8 * 1 = 8
pool-1-thread-3	4 * 9 = 36
pool-1-thread-4	5 * 8 = 40
pool-1-thread-1	7 * 1 = 7
pool-1-thread-4	5 * 9 = 45
pool-1-thread-3	9 * 1 = 9
pool-1-thread-2	8 * 2 = 16
pool-1-thread-2	8 * 3 = 24
pool-1-thread-5	6 * 8 = 48
pool-1-thread-5	6 * 9 = 54
pool-1-thread-2	8 * 4 = 32
pool-1-thread-3	9 * 2 = 18
pool-1-thread-1	7 * 2 = 14
pool-1-thread-3	9 * 3 = 27
pool-1-thread-3	9 * 4 = 36
pool-1-thread-3	9 * 5 = 45
pool-1-thread-3	9 * 6 = 54
pool-1-thread-2	8 * 5 = 40
pool-1-thread-2	8 * 6 = 48
pool-1-thread-2	8 * 7 = 56
pool-1-thread-2	8 * 8 = 64
pool-1-thread-2	8 * 9 = 72
pool-1-thread-3	9 * 7 = 63
pool-1-thread-1	7 * 3 = 21
pool-1-thread-3	9 * 8 = 72
pool-1-thread-3	9 * 9 = 81
pool-1-thread-1	7 * 4 = 28
pool-1-thread-1	7 * 5 = 35
pool-1-thread-1	7 * 6 = 42
pool-1-thread-1	7 * 7 = 49
pool-1-thread-1	7 * 8 = 56
pool-1-thread-1	7 * 9 = 63

Process finished with exit code 0

 

 

 

 

 

4. 자바 8 : List 의 parallelStream

import java.util.ArrayList;

public class Main{
    public static void main(String[] args) {
        ArrayList<Integer> leftList = new ArrayList<>();
        for(int left = 2 ; left < 10 ; left++ ) {
            leftList.add(left);
        }

        leftList.parallelStream().forEach(left ->{
            for(int right = 1 ; right < 10 ; right++){
                System.out.println(Thread.currentThread().getName() + "\t" + left + " * " + right + " = " + (left * right));
            }
        });
    }
}
main	7 * 1 = 7
main	7 * 2 = 14
main	7 * 3 = 21
main	7 * 4 = 28
main	7 * 5 = 35
main	7 * 6 = 42
ForkJoinPool.commonPool-worker-4	8 * 1 = 8
ForkJoinPool.commonPool-worker-2	9 * 1 = 9
ForkJoinPool.commonPool-worker-13	2 * 1 = 2
ForkJoinPool.commonPool-worker-2	9 * 2 = 18
ForkJoinPool.commonPool-worker-11	3 * 1 = 3
ForkJoinPool.commonPool-worker-4	8 * 2 = 16
ForkJoinPool.commonPool-worker-9	4 * 1 = 4
ForkJoinPool.commonPool-worker-9	4 * 2 = 8
main	7 * 7 = 49
main	7 * 8 = 56
main	7 * 9 = 63
ForkJoinPool.commonPool-worker-9	4 * 3 = 12
ForkJoinPool.commonPool-worker-9	4 * 4 = 16
ForkJoinPool.commonPool-worker-6	6 * 1 = 6
ForkJoinPool.commonPool-worker-4	8 * 3 = 24
ForkJoinPool.commonPool-worker-15	5 * 1 = 5
ForkJoinPool.commonPool-worker-15	5 * 2 = 10
ForkJoinPool.commonPool-worker-15	5 * 3 = 15
ForkJoinPool.commonPool-worker-15	5 * 4 = 20
ForkJoinPool.commonPool-worker-11	3 * 2 = 6
ForkJoinPool.commonPool-worker-11	3 * 3 = 9
ForkJoinPool.commonPool-worker-11	3 * 4 = 12
ForkJoinPool.commonPool-worker-2	9 * 3 = 27
ForkJoinPool.commonPool-worker-2	9 * 4 = 36
ForkJoinPool.commonPool-worker-2	9 * 5 = 45
ForkJoinPool.commonPool-worker-13	2 * 2 = 4
ForkJoinPool.commonPool-worker-13	2 * 3 = 6
ForkJoinPool.commonPool-worker-13	2 * 4 = 8
ForkJoinPool.commonPool-worker-13	2 * 5 = 10
ForkJoinPool.commonPool-worker-13	2 * 6 = 12
ForkJoinPool.commonPool-worker-13	2 * 7 = 14
ForkJoinPool.commonPool-worker-2	9 * 6 = 54
ForkJoinPool.commonPool-worker-11	3 * 5 = 15
ForkJoinPool.commonPool-worker-15	5 * 5 = 25
ForkJoinPool.commonPool-worker-4	8 * 4 = 32
ForkJoinPool.commonPool-worker-4	8 * 5 = 40
ForkJoinPool.commonPool-worker-4	8 * 6 = 48
ForkJoinPool.commonPool-worker-6	6 * 2 = 12
ForkJoinPool.commonPool-worker-9	4 * 5 = 20
ForkJoinPool.commonPool-worker-6	6 * 3 = 18
ForkJoinPool.commonPool-worker-4	8 * 7 = 56
ForkJoinPool.commonPool-worker-15	5 * 6 = 30
ForkJoinPool.commonPool-worker-11	3 * 6 = 18
ForkJoinPool.commonPool-worker-11	3 * 7 = 21
ForkJoinPool.commonPool-worker-2	9 * 7 = 63
ForkJoinPool.commonPool-worker-13	2 * 8 = 16
ForkJoinPool.commonPool-worker-2	9 * 8 = 72
ForkJoinPool.commonPool-worker-11	3 * 8 = 24
ForkJoinPool.commonPool-worker-15	5 * 7 = 35
ForkJoinPool.commonPool-worker-4	8 * 8 = 64
ForkJoinPool.commonPool-worker-6	6 * 4 = 24
ForkJoinPool.commonPool-worker-6	6 * 5 = 30
ForkJoinPool.commonPool-worker-9	4 * 6 = 24
ForkJoinPool.commonPool-worker-9	4 * 7 = 28
ForkJoinPool.commonPool-worker-9	4 * 8 = 32
ForkJoinPool.commonPool-worker-6	6 * 6 = 36
ForkJoinPool.commonPool-worker-4	8 * 9 = 72
ForkJoinPool.commonPool-worker-15	5 * 8 = 40
ForkJoinPool.commonPool-worker-11	3 * 9 = 27
ForkJoinPool.commonPool-worker-2	9 * 9 = 81
ForkJoinPool.commonPool-worker-13	2 * 9 = 18
ForkJoinPool.commonPool-worker-15	5 * 9 = 45
ForkJoinPool.commonPool-worker-6	6 * 7 = 42
ForkJoinPool.commonPool-worker-6	6 * 8 = 48
ForkJoinPool.commonPool-worker-6	6 * 9 = 54
ForkJoinPool.commonPool-worker-9	4 * 9 = 36

Process finished with exit code 0

parallelStream 이 내부적으로는 자바 7 의 ForkJoinPool 을 이용해서 구현되있음을 확인할 수 있다.

ForkJoinPool 에 관한 내용은 아래 글을 참조

https://okky.kr/article/345720

 

OKKY | [Java] 쓰레드풀 과 ForkJoinPool

메모리풀/쓰레드풀/캐쉬풀/DB풀  Pool 4총사 중 먼저  쓰레드 풀에 대해서 쉽게 그림으로 배워보아요. 오류나 추가사항이 있으면 댓글로 남겨주시면 소정의  포옹으로 보답을.... 쿨럭 자 시작합니다~! 쓰레드/풀  똑똑똑! 누구니? 쓰레드 에요.. 프로그램(프로세스) 안에서  실행

okky.kr

 

 

 

 

5. 자바 8 : List 의 parallelStream + Thread 크기 지정

import java.util.ArrayList;
import java.util.concurrent.ForkJoinPool;


public class Main{
    public static void main(String[] args) throws Exception{
        ArrayList<Integer> leftList = new ArrayList<>();
        for(int left = 2 ; left < 10 ; left++ ) {
            leftList.add(left);
        }

        ForkJoinPool forkjoinPool = new ForkJoinPool(5);
        forkjoinPool.submit(() -> {
            leftList.parallelStream().forEach(left -> {
                for (int right = 1; right < 10; right++) {
                    System.out.println(Thread.currentThread().getName() + "\t" + left + " * " + right + " = " + (left * right));
                }
            });
        });

        Thread.sleep(1000);
    }
}
ForkJoinPool-1-worker-1	7 * 1 = 7
ForkJoinPool-1-worker-1	7 * 2 = 14
ForkJoinPool-1-worker-4	3 * 1 = 3
ForkJoinPool-1-worker-4	3 * 2 = 6
ForkJoinPool-1-worker-3	9 * 1 = 9
ForkJoinPool-1-worker-3	9 * 2 = 18
ForkJoinPool-1-worker-2	4 * 1 = 4
ForkJoinPool-1-worker-2	4 * 2 = 8
ForkJoinPool-1-worker-2	4 * 3 = 12
ForkJoinPool-1-worker-2	4 * 4 = 16
ForkJoinPool-1-worker-2	4 * 5 = 20
ForkJoinPool-1-worker-2	4 * 6 = 24
ForkJoinPool-1-worker-2	4 * 7 = 28
ForkJoinPool-1-worker-2	4 * 8 = 32
ForkJoinPool-1-worker-3	9 * 3 = 27
ForkJoinPool-1-worker-3	9 * 4 = 36
ForkJoinPool-1-worker-4	3 * 3 = 9
ForkJoinPool-1-worker-4	3 * 4 = 12
ForkJoinPool-1-worker-1	7 * 3 = 21
ForkJoinPool-1-worker-1	7 * 4 = 28
ForkJoinPool-1-worker-1	7 * 5 = 35
ForkJoinPool-1-worker-1	7 * 6 = 42
ForkJoinPool-1-worker-5	6 * 1 = 6
ForkJoinPool-1-worker-5	6 * 2 = 12
ForkJoinPool-1-worker-5	6 * 3 = 18
ForkJoinPool-1-worker-1	7 * 7 = 49
ForkJoinPool-1-worker-1	7 * 8 = 56
ForkJoinPool-1-worker-1	7 * 9 = 63
ForkJoinPool-1-worker-4	3 * 5 = 15
ForkJoinPool-1-worker-4	3 * 6 = 18
ForkJoinPool-1-worker-1	5 * 1 = 5
ForkJoinPool-1-worker-3	9 * 5 = 45
ForkJoinPool-1-worker-3	9 * 6 = 54
ForkJoinPool-1-worker-2	4 * 9 = 36
ForkJoinPool-1-worker-3	9 * 7 = 63
ForkJoinPool-1-worker-3	9 * 8 = 72
ForkJoinPool-1-worker-3	9 * 9 = 81
ForkJoinPool-1-worker-1	5 * 2 = 10
ForkJoinPool-1-worker-4	3 * 7 = 21
ForkJoinPool-1-worker-5	6 * 4 = 24
ForkJoinPool-1-worker-5	6 * 5 = 30
ForkJoinPool-1-worker-5	6 * 6 = 36
ForkJoinPool-1-worker-5	6 * 7 = 42
ForkJoinPool-1-worker-5	6 * 8 = 48
ForkJoinPool-1-worker-4	3 * 8 = 24
ForkJoinPool-1-worker-1	5 * 3 = 15
ForkJoinPool-1-worker-1	5 * 4 = 20
ForkJoinPool-1-worker-3	2 * 1 = 2
ForkJoinPool-1-worker-3	2 * 2 = 4
ForkJoinPool-1-worker-3	2 * 3 = 6
ForkJoinPool-1-worker-2	8 * 1 = 8
ForkJoinPool-1-worker-3	2 * 4 = 8
ForkJoinPool-1-worker-1	5 * 5 = 25
ForkJoinPool-1-worker-4	3 * 9 = 27
ForkJoinPool-1-worker-5	6 * 9 = 54
ForkJoinPool-1-worker-1	5 * 6 = 30
ForkJoinPool-1-worker-1	5 * 7 = 35
ForkJoinPool-1-worker-3	2 * 5 = 10
ForkJoinPool-1-worker-2	8 * 2 = 16
ForkJoinPool-1-worker-3	2 * 6 = 12
ForkJoinPool-1-worker-1	5 * 8 = 40
ForkJoinPool-1-worker-3	2 * 7 = 14
ForkJoinPool-1-worker-3	2 * 8 = 16
ForkJoinPool-1-worker-3	2 * 9 = 18
ForkJoinPool-1-worker-2	8 * 3 = 24
ForkJoinPool-1-worker-1	5 * 9 = 45
ForkJoinPool-1-worker-2	8 * 4 = 32
ForkJoinPool-1-worker-2	8 * 5 = 40
ForkJoinPool-1-worker-2	8 * 6 = 48
ForkJoinPool-1-worker-2	8 * 7 = 56
ForkJoinPool-1-worker-2	8 * 8 = 64
ForkJoinPool-1-worker-2	8 * 9 = 72

Process finished with exit code 0

 

 

 

 

 

*) parallelStream 은 기본적으로 병렬 처리를 하지만 stream 이 마무리 될 때까지 block 이 된다. -> wait 해줄 필요 x

*) ExecutorService 와 ForkJoinPool 은 awaitTerminated 나 invokeAll을 사용해서 wait 해줘야한다.

 

성능에 관하여.

https://hamait.tistory.com/612

 

쓰레드풀 과 ForkJoinPool

쓰레드/풀 똑똑똑! 누구니? 쓰레드 에요.. 프로그램(프로세스) 안에서 실행 되는 하나의 흐름 단위에요. 내부에서 while 을 돌면 엄청 오랬동안 일을 할 수 도 있답니다. 쓰레드 끼리는 값 (메모리) 을 공유 할..

hamait.tistory.com

 

 

 

 

 

'[개발] 기록' 카테고리의 다른 글

mvn vs mvnw  (0) 2019.06.26
자바 8 Stream  (0) 2019.06.06
Java Optional class  (0) 2019.04.25
Reactive connection with DB  (0) 2019.04.18
Lombok을 사용할 때 List 타입 멤버변수 오버라이딩  (0) 2019.04.16