-
Multi-Thread ProgrammingBackEnd/Java 2022. 1. 23. 03:13반응형
Concurrent Software란 동시에 여러 작업을 할 수 있는 Software를 말합니다. Java에서 지원하는 Concurrent Progmming은 멀티프로세싱 (ProcessBuilder)과 멀티쓰레드가 있습니다.
Multi-Thread Progmming 생성 방식
1. Thread 상속
public class MultiThread { public static void main(String[] args) { // 코드 상으로는 Thread-0 출력 이후 main이 출력되어야 하지만, 멀티쓰레드는 동시에 수행되기에 출력 순서를 보장하지 않습니다. MyThread myThread = new MyThread(); myThread.start(); System.out.println(Thread.currentThread().getName()); // [결과]: main } static class MyThread extends Thread { @Override public void run() { System.out.println(Thread.currentThread().getName()); // [결과]: Thread-0 } } }
2. Runnable 구현
public class MultiThread { public static void main(String[] args) { // 코드 상으로는 Thread-0 출력 이후 main이 출력되어야 하지만, 멀티쓰레드는 동시에 수행되기에 출력 순서를 보장하지 않습니다. Thread thread = new Thread(() -> { System.out.println(Thread.currentThread().getName()); // [결과]: Thread-0 }); thread.start(); System.out.println(Thread.currentThread().getName()); // [결과]: main } }
Thread 주요 기능
- sleep: 다른 쓰레드가 처리할 수 있도록 대기하지만 락을 잡고 있습니다. (Deadlock 발생 가능성 존재)
- interrupt: interruptedException을 발생시켜 쓰레드를 깨웁니다.
아래 코드는 thread가 3초 대기 후 종료되어야 하지만 main thread에서 interrupt를 발생시켜 1초 후 종료됩니다.
public class MultiThread { public static void main(String[] args) throws InterruptedException { // 코드 상으로는 Thread-0 출력 이후 main이 출력되어야 하지만, 멀티쓰레드는 동시에 수행되기에 출력 순서를 보장하지 않습니다. Thread thread = new Thread(() -> { System.out.println(Thread.currentThread().getName()); // [결과]: Thread-0 try { Thread.sleep(3000L); // 3초간 sleep } catch (InterruptedException e) { System.out.println("Interrupted!"); return; // Exit } }); thread.start(); System.out.println(Thread.currentThread().getName()); // [결과]: main Thread.sleep(1000L); // 1초간 sleep thread.interrupt(); // thread의 interruptedException을 발생시킵니다. } }
- join: 다른 쓰레드가 끝날 때까지 기다립니다.
아래 코드에서 thread.join(); 생략 시 "Finished!"는 바로 출력되지만, thread.join(); 호출 시에는 thread 수행(3초)이 종료된 후 "Finished!"가 출력됩니다.
public class MultiThread { public static void main(String[] args) throws InterruptedException { // 코드 상으로는 Thread-0 출력 이후 main이 출력되어야 하지만, 멀티쓰레드는 동시에 수행되기에 출력 순서를 보장하지 않습니다. Thread thread = new Thread(() -> { System.out.println(Thread.currentThread().getName()); // [결과]: Thread-0 try { Thread.sleep(3000L); // 3초간 sleep } catch (InterruptedException e) { System.out.println("Interrupted!"); return; // Exit } }); thread.start(); System.out.println(Thread.currentThread().getName()); // [결과]: main thread.join(); // thread가 끝날 때까지 기다립니다. System.out.println("Finished!"); } }
Executors
High-Level Concurrency 프로그래밍으로 쓰레드를 만들고 관리하는 작업을 애플리케이션에서 분리하고, 그런 기능을 Executors에게 위임합니다. Executors는 애플리케이션이 사용할 쓰레드 풀을 만들고, 쓰레드 생명 주기를 관리합니다. 쓰레드로 실행할 작업을 제공할 수 있는 API를 제공합니다.
주요 인터페이스
- Executor: execute(Runnable)
- ExecutorService: Executor 상속 받은 인터페이스로 Callable도 실행할 수 있으며, Executor를 종료시키거나 여러 Callable을 동시에 실행하는 등의 기능을 제공합니다.
- ScheduledExecutorService: ExecutorService를 상속받은 인터페이스로 주기적으로 작업을 실행할 수 있습니다.
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class MultiThread { public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.submit(() -> System.out.println(Thread.currentThread().getName())); // [결과]: pool-1-thread-1 // executorService는 프로세스가 죽지 않기 때문에 명시적으로 종료시켜 주어야 합니다. executorService.shutdown(); // 처리중인 작업 완료후 종료 // executorService.shutdownNow(); // 즉시 종료 ExecutorService fixedExecutorService = Executors.newFixedThreadPool(2); fixedExecutorService.submit(getRunnable()); fixedExecutorService.submit(getRunnable()); fixedExecutorService.submit(getRunnable()); fixedExecutorService.shutdown(); // [결과]: thread-1 과 thread-2 동시 처리 // pool-2-thread-2 // pool-2-thread-1 // pool-2-thread-1 ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); scheduledExecutorService.schedule(getRunnable(), 3, TimeUnit.SECONDS); scheduledExecutorService.shutdown(); // 종료 없이 주기적으로 무한히 수행하는 방식입니다. // scheduledExecutorService.scheduleAtFixedRate(getRunnable(), 1, 2, TimeUnit.SECONDS); } private static Runnable getRunnable() { return () -> { System.out.println(Thread.currentThread().getName()); }; } }
반응형'BackEnd > Java' 카테고리의 다른 글
Java8. CompletableFuture (0) 2022.01.23 Callable과 Future (0) 2022.01.23 Java8. Date-Time API (0) 2022.01.22 Java8. Optional (0) 2022.01.22 Java8. 스트림 (Stream) (0) 2022.01.22