[Java8] Chapter 6-1. Java Concurrent 프로그래밍

 

✍️ Java Concurrent 프로그래밍

  • 동시에 여러 작업을 할 수 있는 소프트웨어
    • 예) 웹 브라우저로 유튜브를 보면서 키보드로 문서에 타이핑을 할 수 있음
    • 예) 이클립스에 코드를 타이핑하면 코드가 입력됨과 동시에 추천 코드를 제안함

 

  •  자바에서 지원하는 Concurrent 프로그래밍
    • 멀티 프로세싱 (ProcessBuilder)
    • 멀티 쓰레드 (본 포스팅에서 다룰 주제) 

 

  • 자바 멀티 쓰레드 프로그래밍
    • Thread
    • Runnable

 

🍊 자바 멀티 쓰레드 프로그래밍

Java 프로세스의 기본 쓰레드는 main 쓰레드다.

public static void main(String[] args) {
	System.out.println(Thread.currentThread().getName());
}

// main

 

하나의 쓰레드에서 다른 쓰레드를 만들 수 있는데, 크게 두 가지 방법이 존재한다. 

첫째로 Thread를 상속하는 방법

둘째로 Runnable을 구현하는 방법

 

Thread를 상속받는 코드부터 살펴보면, Thread를 상속받은 MyThread의 인스턴스를 만들고 start를 호출하면 쓰레드가 생성된다.

public static void main(String[] args) {
	MyThread myThread = new MyThread();
	myThread.start();
	
	System.out.println("main Thread : " + Thread.currentThread().getName());
}

static class MyThread extends Thread{
	@Override
	public void run() {
		System.out.println("new Thread : " + Thread.currentThread().getName());
	}
}

// main Thread : main
// new Thread : Thread-0

 

순서상 new Thread : Thread-0main Thread : main보다 먼저 출력돼야 할 것 같지만 쓰레드의 자원 할당은 OS에 의해 결정되므로 항상 어떤 쓰레드가 먼저 실행될 것이라고 보장할 수 없다. 

 

// 자바 8 스타일
Thread thread = new Thread(() -> {
	System.out.println("람다식 new Thread : " + Thread.currentThread().getName());
});

thread.start();

// 자바8 이전 방식
Thread thread = new Thread(new Runnable() {

	@Override
	public void run() {
		System.out.println("익명 구현 객체 new Thread : " + Thread.currentThread().getName());
	}
});

thread.start();​

 

 

❗️ 쓰레드의 주요 기능

sleep, 현재 쓰레드 대기시키기 

현재 쓰레드를 대기시키면 다른 쓰레드가 자원을 할당받아 일을 하고 대기가 끝나면 다시 자원을 할당받아 일을 한다.

Thread thread = new Thread(() -> {
	try {
		Thread.sleep(1000L);
	} catch (InterruptedException e) {
		e.printStackTrace();
	}

	System.out.println("람다식 new Thread : " + Thread.currentThread().getName());
});

thread.start();

System.out.println("main Thread : " + Thread.currentThread().getName());

// 매우 높은 확률로 main Thread 로그가 먼저 찍힘

 

interrupt, 다른 쓰레드 깨우기

try-catch문을 보면 InterruptedException이 보인다. 쓰레드가 자는 동안 누군가가 자신을 깨우면 InterruptedException이 발생한다. 그렇다면 자고 있는 쓰레드를 깨울 수 있는 방법이 존재한다는 건데 그게 바로 interrupt 메서드다.

Thread thread = new Thread(() -> {
	while(true) {
		System.out.println("반복중... : " + Thread.currentThread().getName());
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			System.out.println("interrupt!!");
			return;
		}
	}
});

thread.start();

System.out.println("main Thread : " + Thread.currentThread().getName());
Thread.sleep(3000);
thread.interrupt();

// main Thread : main
// 반복중... : Thread-0
// 반복중... : Thread-0
// 반복중... : Thread-0
// interrupt!!

 

join, 다른 쓰레드가 끝날 때까지 기다리기

다른 쓰레드가 끝날 때까지 기다리려면 join을 사용하면 된다.

Thread thread = new Thread(() -> {
	try {
		Thread.sleep(3000);
	} catch (InterruptedException e) {
		throw new IllegalStateException(e);
	}
});

thread.start();
System.out.println("waiting for " + thread.getName());

thread.join();
System.out.println("finished : " + thread.getName());

// waiting for Thread-0
// finished : Thread-0

그런데 만약, 다른 쓰레드가 끝나길 기다리는 main 쓰레드를 누군가가 interrupt 한다면 마찬가지 InterruptedException이 발생한다.

 

👋 정리,

지금까지 자바 멀티 쓰레드 프로그래밍의 처리 방법에 대해 알아봤다. 

두 개의 쓰레드만 만들어도 코드가 복잡한데 쓰레드가 10개 100개인 프로그램에서 쓰레드를 하나하나 직접 관리할 수 있을까? 하물며 여기저기서 발생하는 interrupt 그리고 이로 인해 발생하는 InterruptedException은 개발을 어렵게 만든다. 

 

이처럼 여러 쓰레드를 개발자가 하나하나 관리할 수 없다는 문제를 해결하기 위해 Executors가 등장했고, Executors의 사용법을 익히면 Future를 사용할 수 있게 되고, Future의 사용법을 익히면 그제서야 Chapter6의 목적지인 CompletableFuture를 사용할 수 있게 된다. 

 

 

본 내용은 백기선님의 자바8 강의 내용입니다.

 

더 자바, Java 8 - 인프런 | 강의

자바 8에 추가된 기능들은 자바가 제공하는 API는 물론이고 스프링 같은 제 3의 라이브러리 및 프레임워크에서도 널리 사용되고 있습니다. 이 시대의 자바 개발자라면 반드시 알아야 합니다. 이

www.inflearn.com