-
11. 멀티 스레드Java 2021. 9. 4. 14:15
프로세스와 스레드
운영체제에서는 실행 중인 하나의 애플리케이션을 프로세스(process)라고 부른다.
(크롬 브라우저를 두 개 실행했다면 두 개의 크롬 프로세스가 생성된 것이다.)
그렇다면 어떻게 하나의 프로세스가 두 가지 이상의 작업을 처리할 수 있을까? 바로 멀티 스레드(multi thread)에 있다.
스레드(thread)는 사전적 의미로 한 가닥의 실이라는 뜻인데, 한 가지 작업을 실행하기 위해 순차적으로 실행할 코드를 실처럼 이어 놓았다고 해서 유래된 이름이다.
멀티 프로세스들은 운영체제에서 할당받은 자신의 메모리를 가지고 실행하기 때문에 서로 독립적이다.
따라서 다른 하나의 프로세스에서 오류가 발생해도 다른 프로세스에 영향을 미치지 않는다.
멀티 스레드는 하나의 프로세스 내부에 생성되기 때문에 하나의 스레드가 예외를 발생시키면,
프로세스 자체가 종료될 수 있어 다른 스레드에게 영향을 미치게 된다.
Thread 클래스로부터 직접 생성
Thread thread = new Thread(new Runnaber(){ //익명구현객체로 Runnaber 클래스 구현 public void run(){ 스레드가 실행할 코드; } })
멀티 스레드는 동시성(Concurrency), 병렬성(Parallelism)으로 실행된다.
동시성(Concurrency) : 멀티 작업을 위해 하나의 코어에서 멀티 스레드가 번갈아가며 실행하는 성질
병렬성(Parallelism) : 컬티 작업을 위해 컬티 코어에서 개별 스레드를 동시에 실행하는 성질
동기화 메소드 및 동기화 블록
스레드가 사용 중인 객체를 다른 스레드가 변경할 수 없도록 하려면 스레드 작업이 끝날 때까지 객체에 잠금을 걸어서 다른 스레드가 사용할 수 없도록 해야 한다.
멀티 스레드 프로그램에서 단 하나의 스레드만 실행할 수 있는 코드 영역을 임계 영역(critical section)이라고 한다.
자바는 임계 영역을 지정하기 위해 동기화(synchronized) 메소드와 동기화 블록을 제공한다.
스레드가 객체 내부의 동기화 메소드 또는 블록에 들어가면 즉시 객체에 잠금을 걸어 다른 스레드가 임계 영역 코드를 실행하지 못하도록 한다.
//동기화 메소드 public synchronized void method(){ 임계 영역; // 단 하나의 스레드만 실행 } //동기화 블록 public void method(){ //여러 스레드가 실행 가능 영역 synchronized(공유객체){ 임계 영역 //단 하나의 스레드만 실행 } //여러 스레드가 실행 가능 영역 }
스레드 상태
스레드 객체 생성 → 실행 대기 → 실행 → 종료
스레드 객체를 생성하고, start() 메소드를 호출하면 곧바로 스레드가 실행되는 것처럼 보이지만 사실은 실행 대기 상태가 된다. (아직 스케줄링이 되지 않아서 실행을 기다리고 있는 상태)
스레드는 대기 상태와 실행 상태를 번갈아가면서 자신의 run() 메소드를 조금씩 실행한다.
스레드풀(ThreadPool)
갑작스런 병렬 작업의 폭증으로 인한 스레드의 폭증을 막으려면 스레드풀(ThreadPool)을 사용해야 한다.
스레드풀은 작업처리에 사용되는 스레드를 제한된 개수만큼 정해 놓고 작업 큐(Queue)에 들어오는 작업들을 하나씩 스레드가 맡아 처리한다. 작업 처리가 끝난 스레드는 다시 작업큐에서 새로운 작업을 가져와 처리한다. 그렇기 때문에 작업 처리가 끝난 스레드는 다시 작업 큐에서 새로운 작업을 가져와 처리한다.
//스레드풀 생성 - newCachedThreadPool()사용 ExecutorService executorService = Executors.newCachedThreadPool(); //스레드풀 생성 - newFixedThreadPool()사용 ExecutorService executorService = Executors.newFixedThreadPool( Runtime.getRuntime().availableProcessors() //CPU코어의 수만큼 최대 스레드를사용 ); //그 외 스레드풀 생성 ExecutorService threadPool = new ThreadPoolExecutor( 3, //코어 스레드 수 100, //최대 스레드 개수 120L, //놀고 있는 시간 TimeUnit.Seconds, //놀고 있는 시간 단위 new SynchronousQueue<Runnable>() //작업 큐 );
- 초기 스레드 수 : ExecutorService 객체가 생성될 때 기본적으로 생성되는 스레드 수
- 코어 스레드 수 : 스레드풀에서 최소한 유지해야 할 스레드 수
- 최대 스레드 수 : 스레드풀에서 관리하는 최대 스레드 수
작업 생성
Runnable 과 Callable 의 차이점은 작업 처리 완료 후 리턴값이 있느냐 없느냐이다.
//Runnable Runnable task = new Runnable(){ @Override public void run(){ //스레드가 처리할 작업 내용 } } //Callable Callable<T> task = new Callable<T>(){ @Override public T call() throws Exception{ //스레드가 처리할 작업 내용 return T; } }
(스레드 관련해서는 더 공부해서 추가 포스팅이 필요할 것 같다..)
해당 포스트는 이것이 자바다(신용권의 Java 프로그래밍 정복)을 읽은 후 기록한 내용입니다.
참고서적링크 : https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=50563128
이것이 자바다
15년 이상 자바 언어를 교육해온 자바 전문강사의 노하우를 아낌 없이 담아낸 자바 입문서. 저자 직강의 인터넷 강의와 Q/A를 위한 커뮤니티(네이커 카페)까지 무료로 제공하여 자바 개발자로 가
www.aladin.co.kr
'Java' 카테고리의 다른 글
13. 람다식 (0) 2021.09.21 12. 제네릭 (0) 2021.09.12 10. 자바 기본 API 클래스 (0) 2021.08.24 9. 자동 리소스 닫기 (0) 2021.08.21 8. 인터페이스 (0) 2021.08.18