티스토리 뷰

TIL

자바(Java) 스레드(Thread) 공부

해미깨미 2021. 2. 7. 03:14

오늘은 자바 스레드 공부에 대한 필요성을 느껴서 자바 책을 다시 보는 시간을 가졌다.

지원했던 회사에 코딩 테스트 문제로 스레드 관련 문제가 나왔었는데 정말 손도 못 대고 떨어졌다.

그만큼 기본이 안되어있다는 뜻!

좀 더 열심히 하지 않으면 안 되겠다고 느꼈다.

 

스레드로 6개의 로또번호를 비동기로 동시에 중복 없이 만들고 오름차순으로 출력하는 프로그램을 만드는 문제였다.

class Main {

    // 로또번호 개수 상수로 설정
    private static final int LOTTO_NUMBERS = 6;

    public static void main(String[] args) throws InterruptedException {

        // 스레드들이 공용으로 사용 할 객체
        List<Integer> lottoNumberList = new ArrayList<>();
        CountDownLatch countDownLatch = new CountDownLatch(LOTTO_NUMBERS);

        System.out.println("making numbers ...");

        // 6개의 스레드를 만들고 실행
        for (int i=0; i<LOTTO_NUMBERS; i++) {
            Thread lottoNumberMaker = new LottoNumberMaker(lottoNumberList, countDownLatch);
            lottoNumberMaker.start();
        }
		
        // 메인 스레드를 6개의 스레드가 종료되기까지 대기시킴
        countDownLatch.await();

        System.out.println("--------------\nresult numbers");

        lottoNumberList.stream()
                .sorted()
                .forEach(System.out::println);

    }

}
class LottoNumberMaker extends Thread {

    private final List<Integer> lottoNumberList;
    private final CountDownLatch countDownLatch;

    // 생성자로 공용 객체들을 받아준다
    public LottoNumberMaker(List<Integer> lottoNumberList, CountDownLatch countDownLatch) {
        this.lottoNumberList = lottoNumberList;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        int number;
        
        // 생성한 번호가 중복이 아닐 때 까지 생성
        do {
            number = new Random().nextInt(45) + 1;
            System.out.println(this.getName() + " make a number " + number);
        } while (lottoNumberList.contains(number));
        
        // 리스트에 번호를 추가하고 스레드가 종료되기 전에 카운트 다운
        lottoNumberList.add(number);
        countDownLatch.countDown();
    }

}

실행결과는 다음과 같다

 

문제를 풀면서 가장 어려웠던 점은 메인 스레드를 대기시켰다가 스레드 6개가 작업을 마치면 결과를 출력하게 만드는 것이었다.

lottoNumberMaker.join()을 사용하면 스레드가 순서대로 실행돼서 번호가 동시에 만들어지지 않게 된다.

그래서 CountDownLatch 클래스를 이용해서 문제를 해결했다.

 

await() 메소드로 메인 스레드를 일시 정지시키고 CountDownLatch 생성자에 파라미터로 넣어준 카운트 개수를 run() 함수가 끝날 때마다 countDown() 메소드로 하나씩 줄여준다.

카운트가 0이 되면 대기하고 있던 메인 스레드가 다시 실행하면서 결과를 출력하게 만들었다.


++ 2020.02.08 오전 1:43 내용 추가

스레드 풀을 사용해서도 구현해 봤다.

class Main {

    private static final int LOTTO_NUMBERS = 6;

    public static void main(String[] args) throws InterruptedException {

        ExecutorService executorService = Executors.newFixedThreadPool(LOTTO_NUMBERS);

        List<Integer> lottoNumberList = new ArrayList<>();

        // 6개의 스레드를 스레드 풀에 작업 요청
        for (int i=0; i<LOTTO_NUMBERS; i++) {
            executorService.submit(
                    () -> {
                        int number;

                        do {
                            number = new Random().nextInt(45)+1;
                            System.out.println(Thread.currentThread().getName() + " make a " + number);
                        } while (lottoNumberList.contains(number));

                        lottoNumberList.add(number);
                    });
        }

        // 결과 출력을 위해 메인 스레드를 0.1초 정지시킴
        Thread.sleep(100);

        // 리스트의 숫자들을 오름차순으로 정렬 후 순서대로 출력
        lottoNumberList.stream()
                .sorted().forEach(System.out::println);

        // 스레드 풀 종료
        executorService.shutdown();

    }

}

실행결과는 다음과 같다

'TIL' 카테고리의 다른 글

스프링 시큐리티(Spring Security) 간단 정리  (0) 2021.02.09
자바 람다식에 대해  (0) 2021.02.08
스프링 어노테이션에 대해 알게 된 사실  (0) 2021.02.05
타임리프(Thymeleaf)에 대해  (0) 2021.02.05
Spring 빌드 클린  (2) 2021.02.04
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함