본문 바로가기

자바

[스레드] 11. 스레드풀(2)

예제1)

package ex09_execute_submit;

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

public class ExecuteVsSubmitExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        for (int i = 0; i < 10; i++) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorService;
                    int poolSize = threadPoolExecutor.getPoolSize();

                    String threadName = Thread.currentThread().getName();
                    System.out.println("[총 스레드 개수: " + poolSize + "] 작업 처리-" + threadName);
                }
            };
            executorService.execute(runnable);
        }

        executorService.shutdown();
    }
}

결과:

총 스레드 개수: 2] 작업 처리-pool-1-thread-1
총 스레드 개수: 2] 작업 처리-pool-1-thread-2
총 스레드 개수: 2] 작업 처리-pool-1-thread-2
총 스레드 개수: 2] 작업 처리-pool-1-thread-1
총 스레드 개수: 2] 작업 처리-pool-1-thread-2
총 스레드 개수: 2] 작업 처리-pool-1-thread-1
총 스레드 개수: 2] 작업 처리-pool-1-thread-2
총 스레드 개수: 2] 작업 처리-pool-1-thread-1
총 스레드 개수: 2] 작업 처리-pool-1-thread-1
총 스레드 개수: 2] 작업 처리-pool-1-thread-2

 

예제2) 예외가 발생할 경우

package ex09_execute_submit;

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

public class ExecuteVsSubmitExample {
    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        for (int i = 0; i < 10; i++) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorService;
                    int poolSize = threadPoolExecutor.getPoolSize();

                    String threadName = Thread.currentThread().getName();
                    System.out.println("[총 스레드 개수: " + poolSize + "] 작업 처리-" + threadName);
                    int value = Integer.parseInt("skfjlkwefj");
                }
            };
            executorService.execute(runnable);

            Thread.sleep(100);
        }

        executorService.shutdown();
    }
}

결과:

[총 스레드 개수: 1] 작업 처리-pool-1-thread-1
Exception in thread "pool-1-thread-1" java.lang.NumberFormatException: For input string: "skfjlkwefj"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at ex09_execute_submit.ExecuteVsSubmitExample$1.run(ExecuteVsSubmitExample.java:20)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
[총 스레드 개수: 2] 작업 처리-pool-1-thread-3
Exception in thread "pool-1-thread-3" java.lang.NumberFormatException: For input string: "skfjlkwefj"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at ex09_execute_submit.ExecuteVsSubmitExample$1.run(ExecuteVsSubmitExample.java:20)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
[총 스레드 개수: 2] 작업 처리-pool-1-thread-2
Exception in thread "pool-1-thread-2" java.lang.NumberFormatException: For input string: "skfjlkwefj"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at ex09_execute_submit.ExecuteVsSubmitExample$1.run(ExecuteVsSubmitExample.java:20)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
[총 스레드 개수: 2] 작업 처리-pool-1-thread-4
Exception in thread "pool-1-thread-4" java.lang.NumberFormatException: For input string: "skfjlkwefj"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at ex09_execute_submit.ExecuteVsSubmitExample$1.run(ExecuteVsSubmitExample.java:20)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
[총 스레드 개수: 2] 작업 처리-pool-1-thread-5
Exception in thread "pool-1-thread-5" java.lang.NumberFormatException: For input string: "skfjlkwefj"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at ex09_execute_submit.ExecuteVsSubmitExample$1.run(ExecuteVsSubmitExample.java:20)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
[총 스레드 개수: 2] 작업 처리-pool-1-thread-6
Exception in thread "pool-1-thread-6" java.lang.NumberFormatException: For input string: "skfjlkwefj"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at ex09_execute_submit.ExecuteVsSubmitExample$1.run(ExecuteVsSubmitExample.java:20)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
[총 스레드 개수: 2] 작업 처리-pool-1-thread-7
Exception in thread "pool-1-thread-7" java.lang.NumberFormatException: For input string: "skfjlkwefj"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at ex09_execute_submit.ExecuteVsSubmitExample$1.run(ExecuteVsSubmitExample.java:20)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
[총 스레드 개수: 2] 작업 처리-pool-1-thread-8
Exception in thread "pool-1-thread-8" java.lang.NumberFormatException: For input string: "skfjlkwefj"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at ex09_execute_submit.ExecuteVsSubmitExample$1.run(ExecuteVsSubmitExample.java:20)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
[총 스레드 개수: 2] 작업 처리-pool-1-thread-9
Exception in thread "pool-1-thread-9" java.lang.NumberFormatException: For input string: "skfjlkwefj"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at ex09_execute_submit.ExecuteVsSubmitExample$1.run(ExecuteVsSubmitExample.java:20)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
[총 스레드 개수: 2] 작업 처리-pool-1-thread-10
Exception in thread "pool-1-thread-10" java.lang.NumberFormatException: For input string: "skfjlkwefj"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at ex09_execute_submit.ExecuteVsSubmitExample$1.run(ExecuteVsSubmitExample.java:20)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)

 

예제3) submit 메소드

package ex09_execute_submit;

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

public class ExecuteVsSubmitExample {
    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        for (int i = 0; i < 10; i++) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorService;
                    int poolSize = threadPoolExecutor.getPoolSize();

                    String threadName = Thread.currentThread().getName();
                    System.out.println("[총 스레드 개수: " + poolSize + "] 작업 처리-" + threadName);
                    int value = Integer.parseInt("skfjlkwefj");
                }
            };
//            executorService.execute(runnable);
            executorService.submit(runnable);

            Thread.sleep(100);
        }

        executorService.shutdown();
    }
}

결과:

[총 스레드 개수: 1] 작업 처리-pool-1-thread-1
[총 스레드 개수: 2] 작업 처리-pool-1-thread-2
[총 스레드 개수: 2] 작업 처리-pool-1-thread-1
[총 스레드 개수: 2] 작업 처리-pool-1-thread-2
[총 스레드 개수: 2] 작업 처리-pool-1-thread-1
[총 스레드 개수: 2] 작업 처리-pool-1-thread-2
[총 스레드 개수: 2] 작업 처리-pool-1-thread-1
[총 스레드 개수: 2] 작업 처리-pool-1-thread-2
[총 스레드 개수: 2] 작업 처리-pool-1-thread-1
[총 스레드 개수: 2] 작업 처리-pool-1-thread-2

 

 

블로킹 방식의 작업 완료 통보 받기

Future<?> submit(Runnable task);
<T> Future<T> submit(Runnable task, T result);
<T> Future<T> submit(Callable<T> task);

- Runnable 또는 Callable 을 작업큐에 저장

- 리턴된 Future를 통해 작업 처리 결과 얻음

 

Future

- 작업결과가 아니라 지연 완료(pending completion)객체

- 작업이 완료될때까지 기다렸다가 최종 결과를 얻기 위해서 get() 메소드 사용

V get() throws InterruptedException, ExecutionException;

- 작업이 완료될 때까지 블로킹되었다가 처리 결과 V를 리턴

V get(long timeout, TimeUnit unit)
    throws InterruptedException, ExecutionException, TimeoutException;

- timeout 시간동안 작업이 완료되면 결과 V를 리턴하지만, 작업이 완료되지 않으면 TimeoutException 발생

 

* Future의 get() 은 UI 스레드에서 호출하면 안됨.

 

 

예제4)

package ex09_execute_submit;

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

public class NoResultExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(
                Runtime.getRuntime().availableProcessors()     // cpu의 코어수
        );

        System.out.println("[작업 처리 요청]");
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                int sum = 0;
                for (int i = 0; i < 10; i++) {
                    sum += i;
                }
                System.out.println("[처리결과]" + sum);
            }
        };

        Future future = executorService.submit(runnable);

        try {
            future.get();
            System.out.println("[작업 처리 완료]");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        executorService.shutdown();
    }
}

결과:

[작업 처리 요청]
[처리결과]45
[작업 처리 완료]

 

'자바' 카테고리의 다른 글

dto 복사에 관하여  (0) 2022.12.08
[스레드] 12. 스레드풀(3)  (0) 2022.05.07
[스레드] 10. 스레드풀(1) ExecutorService  (0) 2022.05.01
[스레드] 9. 스레드 그룹  (0) 2022.05.01
[스레드] 8. 데몬 스레드  (0) 2022.05.01