Backend/JAVA

[Java] ๋น„๋™๊ธฐ ์ž‘์—… ์ฒ˜๋ฆฌ (ExecutorService VS CompletableFuture)

dddzr 2025. 2. 23. 17:09

๐Ÿ“Œ Java์—์„œ ๋น„๋™๊ธฐ ์ž‘์—… ์ฒ˜๋ฆฌ

Java์—์„œ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์–‘ํ•˜์ง€๋งŒ, ExecutorService์™€ CompletableFuture๊ฐ€ ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ด๊ณ  ๋„๋ฆฌ ์‚ฌ์šฉ๋œ๋‹ค.๐Ÿ˜†

 

โœ… 1. Thread ์ง์ ‘ ์‚ฌ์šฉ

Thread ํด๋ž˜์Šค๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•˜์—ฌ ์ž‘์—…์„ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•.

 

๐Ÿ“– ์˜ˆ์ œ

Thread thread = new Thread(() -> {
    System.out.println("๋น„๋™๊ธฐ ์ž‘์—… ์‹คํ–‰");
});

thread.start();

 

โœ” ์žฅ์ 

  • ๊ฐ„๋‹จํ•œ ์ž‘์—…์— ์ ํ•ฉ.

โŒ ๋‹จ์ 

  • ์Šค๋ ˆ๋“œ ํ’€ ๊ด€๋ฆฌ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ , ์ง์ ‘ ๊ด€๋ฆฌํ•ด์•ผ ํ•ด์„œ ๋ณต์žกํ•ด์ง.
  • ์„ฑ๋Šฅ ๋ฐ ์ž์› ๊ด€๋ฆฌ ์ธก๋ฉด์—์„œ ๋น„ํšจ์œจ์ .

 

โœ… 2. ExecutorService

์Šค๋ ˆ๋“œ ํ’€์„ ๊ด€๋ฆฌํ•˜๋ฉฐ ํšจ์œจ์ ์œผ๋กœ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌ.

Runnable ๋˜๋Š” Callable์„ ํ™œ์šฉํ•˜๋Š” ๊ฒŒ ๊ฐ€์žฅ ์ผ๋ฐ˜์ .

 

1๏ธโƒฃ ExecutorService๋Š” ์ง์ ‘ ์Šค๋ ˆ๋“œ ํ’€์„ ์ƒ์„ฑํ•˜์—ฌ ์ž‘์—…์„ ์‹คํ–‰.

2๏ธโƒฃ submit() ๋ฉ”์„œ๋“œ๋Š” ์ž‘์—…์„ ์Šค๋ ˆ๋“œ ํ’€์˜ ํ์— ์ถ”๊ฐ€ํ•˜์—ฌ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰.

3๏ธโƒฃ ์ž‘์—… ์™„๋ฃŒ ํ›„ shutdown()์„ ํ˜ธ์ถœํ•˜์—ฌ ์Šค๋ ˆ๋“œ ํ’€์„ ์ข…๋ฃŒ.

 

๐Ÿ“– ์˜ˆ์ œ

//์Šค๋ ˆ๋“œ ํ’€ ํฌ๊ธฐ ์„ค์ • (๋™์‹œ์— ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์ž‘์—… ์ˆ˜ ์ œํ•œ)
ExecutorService executor = Executors.newFixedThreadPool(5); 
executor.submit(() -> {
    System.out.println("๋น„๋™๊ธฐ ์ž‘์—… ์‹คํ–‰");
});

executor.shutdown();

 

๐Ÿ“– Runnable๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ (๋ฐ˜ํ™˜๊ฐ’ โŒ)

ExecutorService executor = Executors.newFixedThreadPool(2);
Runnable task = () -> {
    System.out.println("Runnable: ๋น„๋™๊ธฐ ์ž‘์—… ์‹คํ–‰ ์ค‘...");
};
executor.submit(task);
executor.shutdown();

 

๐Ÿ“– Callableํ•จ๊ป˜ ์‚ฌ์šฉ (๋ฐ˜ํ™˜๊ฐ’ โญ•)

import java.util.concurrent.*;

public class CallableExample {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(2);

        Callable<String> task = () -> {
            return "Callable: ๋น„๋™๊ธฐ ์ž‘์—… ์™„๋ฃŒ!";
        };

        Future<String> future = executor.submit(task); // ์ž‘์—… ์‹คํ–‰ ํ›„ Future ๊ฐ์ฒด ๋ฐ˜ํ™˜
        System.out.println(future.get()); // get() ํ˜ธ์ถœํ•ด์„œ ๊ฒฐ๊ณผ ๋ฐ›๊ธฐ
        executor.shutdown();
    }
}

 

โœ” ์žฅ์ 

  • ์Šค๋ ˆ๋“œ ํ’€์„ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ์„ฑ๋Šฅ๊ณผ ์ž์› ๊ด€๋ฆฌ๊ฐ€ ํšจ์œจ์ .
  • ๋‹ค์–‘ํ•œ ์‹คํ–‰ ์ •์ฑ… ์ œ๊ณต (FixedThreadPool, CachedThreadPool, SingleThreadExecutor ๋“ฑ).
  • ์Šค๋ ˆ๋“œ ํ’€ ํฌ๊ธฐ ๋ฐ ๋™์ž‘์„ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ด ๊ฐ€๋Šฅ.

โŒ ๋‹จ์ 

  • ์ž‘์—… ์™„๋ฃŒ ํ›„์˜ ๊ฒฐ๊ณผ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ฑฐ๋‚˜ ์ฒด์ด๋‹ํ•˜๋ ค๋ฉด ์ˆ˜๋™์œผ๋กœ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ (ํ˜น์€ CompletableFuture ์‚ฌ์šฉ).
  • ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์Œ.

 

โœ… 3. CompletableFuture

Java 8๋ถ€ํ„ฐ ๋„์ž…๋œ ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ API.

  • CompletableFuture.runAsync()๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ForkJoinPool.commonPool์„ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌ.
  • ๋ฐ˜ํ™˜ ๊ฐ’ ์—†์ด ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰๋˜๋Š” ์ž‘์—…์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
  • ForkJoinPool ๋Œ€์‹  ์ปค์Šคํ…€ ์Šค๋ ˆ๋“œ ํ’€์„ ์ง€์ •ํ•˜๋ ค๋ฉด ์ถ”๊ฐ€ ์ธ์ž๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
    CompletableFuture.runAsync(() -> { /* ์ž‘์—… ๋กœ์ง */ }, executorService);
  • ์ฒด์ด๋‹(thenApply, thenAccept, thenRun)์„ ํ™œ์šฉํ•˜๋ฉด ์ž‘์—…์„ ์‰ฝ๊ฒŒ ์—ฐ๊ฒฐ

 

๐Ÿ“– runAsync ์‚ฌ์šฉ (๋ฐ˜ํ™˜๊ฐ’ โŒ)

CompletableFuture.runAsync(() -> {
    System.out.println("Runnable์ฒ˜๋Ÿผ ์‹คํ–‰๋จ!");
});

// ํ•จ์ˆ˜ ๋ฆฌํ„ด๊ฐ’ ํƒ€์ž…
public CompletableFuture<Void> function(String param) throws Exception {
    return CompletableFuture.runAsync(() -> {
        // ์ž‘์—… ๋กœ์ง
    });
}

 

๐Ÿ“– supplyAsync ์‚ฌ์šฉ (๋ฐ˜ํ™˜๊ฐ’ โญ•)

CompletableFuture.supplyAsync(() -> {
    return "๋น„๋™๊ธฐ ์ž‘์—… ๊ฒฐ๊ณผ";
}).thenAccept(result -> {
    System.out.println("๊ฒฐ๊ณผ: " + result);
});

// or

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    return "Callable์ฒ˜๋Ÿผ ์‹คํ–‰๋จ!";
});

future.thenAccept(System.out::println); // ๊ฒฐ๊ณผ ์ถœ๋ ฅ

 

๐Ÿ“– ์ปค์Šคํ…€ ์Šค๋ ˆ๋“œ ํ’€ + CompletableFuture

ExecutorService executor = Executors.newFixedThreadPool(2);
CompletableFuture.runAsync(() -> {
    // ์ž‘์—… ๋กœ์ง
}, executor);

executor.shutdown();

 

๐Ÿ“– ๋น„๋™๊ธฐ ์ž‘์—… ์—ฌ๋Ÿฌ๊ฐœ ์™„๋ฃŒ ๊ธฐ๋‹ค๋ฆฌ๊ธฐ

List<CompletableFuture<Void>> futures = new ArrayList<>();

for (int i = 0; i < 5; i++) {
    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        try {
            Thread.sleep(1000); // 1์ดˆ ๋™์•ˆ ๋Œ€๊ธฐ
            System.out.println(Thread.currentThread().getName() + " ์ž‘์—… ์™„๋ฃŒ!");
            
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });    
    futures.add(future);
}

// ๋ชจ๋“  ์ž‘์—…์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

System.out.println("โœ… ๋ชจ๋“  ๋น„๋™๊ธฐ ์ž‘์—… ์™„๋ฃŒ ํ›„ ์‹คํ–‰!");


โœ” ์žฅ์ 

  • ๋น„๋™๊ธฐ ์ž‘์—… ์ฒด์ด๋‹ ๋ฐ ๊ฒฐ๊ณผ/์—๋Ÿฌ ์ฒ˜๋ฆฌ ๊ฐ„ํŽธ.
  • ForkJoinPool๊ณผ ์ž˜ ํ†ตํ•ฉ๋œ๋‹ค.
  • ๊ธฐ๋ณธ์ ์œผ๋กœ ์Šค๋ ˆ๋“œ ํ’€์„ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š” ์—†์Œ.

โŒ ๋‹จ์ 

  • ๊ฐ„๋‹จํ•œ ์ž‘์—…์— ์‚ฌ์šฉํ•˜๋ฉด ์˜คํžˆ๋ ค ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์Œ.
  • ๊ธฐ๋ณธ ForkJoinPool์˜ ํฌ๊ธฐ๊ฐ€ ์ œํ•œ์ ์ด๋ฏ€๋กœ ๋Œ€๋Ÿ‰์˜ ์ž‘์—…์ด ๋ฐœ์ƒํ•˜๋ฉด ์ปค์Šคํ…€ ์Šค๋ ˆ๋“œ ํ’€ ํ•„์š”.

 


๐Ÿ”ฅ ExecutorService VS CompletableFuture

ํŠน์ง• ExecutorService CompletableFuture
์‚ฌ์šฉ ๋ชฉ์  ์Šค๋ ˆ๋“œ ํ’€ ์ง์ ‘ ๊ด€๋ฆฌ & ์ž‘์—… ์‹คํ–‰ ๋น„๋™๊ธฐ ์ž‘์—… ์ฒด์ด๋‹ & ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ
์Šค๋ ˆ๋“œ ๊ด€๋ฆฌ ์ง์ ‘ ์Šค๋ ˆ๋“œ ํ’€ ํฌ๊ธฐ ์„ค์ • ๋ฐ ๊ด€๋ฆฌ ํ•„์š” ๊ธฐ๋ณธ์ ์œผ๋กœ ForkJoinPool.commonPool ์‚ฌ์šฉ (ํ•„์š”์‹œ ์ปค์Šคํ…€ ๊ฐ€๋Šฅ)
์ž‘์—… ์—ฐ๊ฒฐ (์ฒด์ด๋‹) ์ง์ ‘ ์ถ”๊ฐ€ ๊ตฌํ˜„ ํ•„์š” (Future ์‚ฌ์šฉ ์‹œ ์ œํ•œ์ ) thenApply, thenAccept, handle ๋“ฑ์„ ํ†ตํ•ด ์‰ฝ๊ฒŒ ์—ฐ๊ฒฐ 
์˜ˆ์™ธ ์ฒ˜๋ฆฌ try-catch๋กœ ์ง์ ‘ ์ฒ˜๋ฆฌ exceptionally, handle ์ง€์›
์ง์ ‘ ์ข…๋ฃŒ ํ•„์š” shutdown() ํ˜ธ์ถœ ํ•„์š” ๊ธฐ๋ณธ ํ’€(commonPool)์€ JVM ์ข…๋ฃŒ ์‹œ ์ž๋™ ์ข…๋ฃŒ
์ถ”๊ฐ€ ์ž‘์—… ์ง€์› ์ œํ•œ์  (submit ๋ฐ Future.get์œผ๋กœ ๊ฒฐ๊ณผ ํ™•์ธ) ์—ฐ์† ์ž‘์—…, ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ ์ง€์›
์ฝ”๋“œ ๊ฐ„๊ฒฐ์„ฑ ๋น„๊ต์  ์žฅํ™ฉํ•  ์ˆ˜ ์žˆ์Œ ๊ฐ„๊ฒฐํ•˜๊ณ  ์ฝ๊ธฐ ์‰ฌ์›€

 

๐Ÿš€ ๊ฒฐ๋ก 

  • ์ž‘์—… ๊ฐ„ ์—ฐ๊ฒฐ & ๊ฐ„๋‹จํ•œ ๋น„๋™๊ธฐ ์ž‘์—…CompletableFuture ์‚ฌ์šฉ ์ถ”์ฒœ!
  • ์Šค๋ ˆ๋“œ ํ’€์„ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•ด์•ผ ํ•  ๋•ŒExecutorService ์‚ฌ์šฉ ์ถ”์ฒœ!


'Backend > JAVA' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

JNDI๋ž€?  (0) 2025.02.26
์ž๋ฐ”(Spring) ๊ธฐ๋ณธ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ  (0) 2025.02.23
HttpURLConnection  (0) 2024.06.07
๋ธ”๋กํ‚นํ(Blocking Queue)  (0) 2024.06.05
Callable, Runnable, Future  (0) 2024.06.05