process
현재 실행중인 프로그램의 상태
메모리
코드
핸들
Thread
- 실행 중인 프로그램에서 1개의 순차적인 제어 흐름의 추상적인 개념
- 하나의 프로그램에서 각각의 독립적인 작업을 수행하는 것을 다중 쓰레딩이라 하며, 이 경우 동시(concurrently)에 여러가지 작업이 가능하다
- 쓰레드는 자신의 코드를 모두 실행하고 나면 자동적으로 죽는다
- 쓰레드를 생성한 후 .Start() 메소드를 사용해야 실행된다. 사용하지 않을 경우 호출하더라도 실행 되지 않는다
왜 멀티 쓰레드를 쓰는가?
코드 작성이 쉽다. 각각의 역할분담을 하는 것으로 복잡한 작업을 쉽게 만들 수 있다
쓰레드 생성하기
생성 코드
new Thread()
new Thread(String name)
Runable : 자바에서는 할 일을 가리킨다. 특정 작업을 가지고 있는 것
public class ThreadTest {
public void newTreadStart(){
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i<10; i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i : " + i);
}
}
}).start();
}
public void startMyThread(){
new MyThread().start();
}
public class MyThread extends Thread {
@Override
public void run() {
for(int i=0; i<10; i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("j : " + i);
}
}
}
}
Runnable -> non Runnable로 만드는 함수
Thread.sleep()
otherThread.join()
Obj.wait()
non Runnable -> Runnable로 만드는 함수
timeout
otherThread exits
Obj.notify()
Obj.notigyAll()
쓰레드 스케쥴링
- Runnable 상태의 많은 쓰레드가 존재할 때, 이들 중 실질적으로 실행되는 CPU 타임을 갖는 실행 시간을 배분하는 방식이 스케쥴링이다
- 아중 프로세서 시스템에서는 여러 개의 쓰레드가 여러 개의 프로세서에 의해 병렬로 실행될 수 있다
- 플랫폼에 따른 프로세서의 배분방식
시분할 프로세서 배분(time-slicing scheduling)
단순 프로세서 배분(non-preemptive scheduling)
쓰레드 우선 순위
- 자바의 모든 쓰레드는 우선순위를 가진다
- 우선 순위 값은 기본적으로 부모 쓰레드에서 상속 받는다(디폴트 5)
- 우선 순위 값
Thread.MIN_PRIORITY(=1) ~ Thread.MAX_PRIORITY(=10)
Runnable 상태의 쓰레드 중 우선 순위 값이 높은 쓰레드가 실행 시간을 많이 할당 받을 가능성이 높다
디폴트 값은 Thread.NORM_PRIORITY (=5)
- 관련 메소드
setPriority(int newPriority)
int getPriority()
쓰레드 인터럽트
다른 쓰레드에 간단한 동기 신호(예외 객체)를 보낸다
쓰레드에 인터럽트를 걸면 exception을 보내고 멈출 거라고 생각하지만 잘못된 상식이다. 실행 중인 코드는 모두 실행 되며, sleep상태 등의 non runnable state일 때 예외 객체를 발생시킨다
동기화(Synchronization)
- 동기화가 필요한 이유
- 두 개의 쓰레드가 같은 객체를 동시에 사용한다면 연산 도중 다른 쓰레드에 의해 연산 작업이 왜곡될 수 있다
- 모든 객체는 1개의 자물쇠를 가지고 있어 객체에 접근하는 쓰레드가 특정 영역에 접근 시 잠금 장치를 함으로써 쓰레드 작업을 관리할 수 있다
- 동기화 작업을 처리할 때 가장 중요한 것은 동기화 처리에 대한 설계이다. 잘못된 설계에 의해 데드락에 빠질 수 있다
synchronized 수행문
객체의 동기화 메소드를 호출하지 안ㅇㅎ고도 현재 객체 또는 다른 객체를 잠금 상태에 놓이게 할 수 있다.
synchronized(참조자료형수식) {...}
synchronized 인스턴스 메소드
- 이 객체의 자물쇠를 채운다
- 메소드의 몸체를 실행한다
- 이 객체의 자물쇠를 풀어준다
synchronized 클래스 메소드
- Class 객체의 자물쇠를 채운다
- 메소드의 몸체를 실행한다
- Class 객체의 자물쇠를 풀어준다
대기와 통지
- 락 매커니즘처럼 이러한 매커니즘의 주요 목적은 쓰레드간 통신의 효율성을 위해 조건 변수를 구현하는 것이다
- 동기화 메소드처럼 wait(synchronized 되어 있는 쓰레드에만 사용 가능)과 notify 매커니즘도 자바에서는 객체에서 이용할 수 있도록 Object 클래스의 메소드로 구현되어 있다
java.util.concurrent.atomic
값을 읽기와 변경을 동시에 수행하여 멀티 쓰레드 환경에서 값이 잘못 변경되는 것을 막기 위한 클래스들의 패키지
AtomicBoolean, AtomicInteger, ...
AtomicInteger는 getAndSet과 같은 함수 제공
Thread Pool
쓰레드를 매번 생성시 발생하는 오버헤드를 줄이기 위해 이용한다
java.util.concurrent.Excutors라는 ThreadPool Factory를 이용하여 ExcutorService를 생성한 다음, execute함수에 Runnable객체를 넣어 실행한다
public void onCreate() {
ExecutorService ec = Executors.newFixedThreadPool(5); // 5개의 쓰레드 풀을 생성해 쓰레드 갯수를 5개로 제한
for(int i=0; i<10; i++) {
executor.execute(new MyTask());
}
executor.shutdown();
while(!executor.isTerminated()) {
}
System.out.println("finish all thread");
}
댓글