Java Concurrency

Java Concurrency 

Thread 생성
- 자바에서 스레드를 생성하는 방법은 2가지 이다. java.lang.Thread와 java.lang.Runnable 2가지가 있다.

Thread를 상속받는 방법. 
class Comet extends Thread {
    public void run() {
        System.out.println("Orbiting");
        orbit();
    }
}
Comet halley = new Comet();
hally.run();

Runnable를 구현하는 방법.
class Asteroid implements Runnable {
    plublic void run() {
        System.out.println("Orbiting");
        orbit();
    }
}
Asteroid majaAsteroid = new Asteroid();
Thread majaThread = new Thread(majaAsteroid);
majaThread.run();
Lambda 표현식을 이용하는 방법. 
Runnable asteroid = () -> {
    System.out.println("Orbiting");
    orbit();
}
Thread asteroidThread1 = new Thread(asteroid);
Thread asteroidThread2 = new Thread(asteroid);
asteroidThread1.run();
asteroidThread2.run();

Thread 상태 

NEW : 스레드는 생성되었으나 시작되지 않은 상태.
RUNNABLE : 스레드가 실행 가능한 상태가 되었다.
BLOCKED : "alive" 스레드로 모니터 락을 기다리는 블록된 상태.
WAITING : "alive" 스레드로 다른 스레드를 기다리는 동안 wait()혹은 join()을 호출한다.
TIMED_WAITING : "alive"스레드로 특정 시간동안 다른 스레드를 기다린다. sleeping
TERMINATED : 스레드가 완료된 경우

스레드 우선순위

스레드 우선순위는 1 ~ 10단계로 둘수 있다. 기본은 5이다.
MIN_PRIORITY, NORM_PRIORITY,  MAX_PRIORITY 를 이용하여 우선순위를 탐색 할 수 있다.

System.out.println(Thread.MAX_PRIORITY);
낮은 우선순위는 높은 우선순위의 스레드에 양보하게 된다.

공통 메소드 

getPriority() : 스레드의 우선순위를 반환한다.
getState() : 스레드의 상태를 반환한다.
interrupt() : 스레드에 인터럽트를 건다.
isAlive() : 스레드가 얼라이브 상태인지 검사한다.
isInterrupted() : 스레드가 인터럽트 되었는지 검사한다.
join() : 이 메소드를 호출하여 스레드를 기다린다. 이는 객체가 종료 되었음을 알려준다.
setPriority(int) : 스레드의 우선순위를 설정한다.
start() : 스레드를 실행 가능 상태의 위치로 옮긴다.


notify() : 스레드에게 깨어나고, 실행하라고 해준다.
notifyAll() : 모든 기다리는 스레드나 리소스에게 깨어나게 한다. 그리고 스레드 중의 하나를 선택해서 실행한다.
wait() : 다른 스레드가 notify를 호출하거나 notifyAll()을 호출하기 전까지 대기 하게 한다.

# 중요 :
만약 wait() 와 notify()를 호출할때 스레드의 상태가 interrupted flag가 true로 설정된 경우 InterruptedException이 발생된다.

정적 스레드 메소드 : 

activeCount() : 현재 스레드 그룹에서 스레드의 수를 반환한다.
currentThread() : 현재 실행중인 스레드의 레퍼런스를 반환한다.
interrupted() : 현재 실행중인 스레드의 인터럽트 여부를 체크한다.
sleep(long) : 지정된 밀리 세컨동안 실행되는 스레드를 블록한다.
yield() : 현재 스레에게 다른 스레드가 수행할 수 있도록 알려준다.

Synchronization

synchronized 키워드는 특정 블록이나 메소드에게 락을 수행하도록 해준다.
Locks는 블록이나 메소드에 걸리며 이는 매우 중요하게 공유되어야할 리소스에 접근할때 이용하게 된다. 이 모니터 락은 브레이스를 열고 닫는 것으로 시작과 종료가 된다.

객체 인스턴스 t에 동기화 락을 걸어준다.
synchronized (t) {
    // Block body
}
객체 인스턴스 this 에 동기화 락을 걸어준다.
synchronized (this) {
    // Block body
}
raise() 메소드에 동기화 락을 걸어준다.
synchronized void raise() {
    // Method body
}
void raise() {
    synchronized (this) {
        // Method body
    }
}
상기 두 처리는 동일하다.

다음은 정적 메소드에 동기화 락을 걸어 준 예이다.
class Telescope {
    synchronized static void calivrate() {
        // Method body
    }
}

동시성 유틸리티

java에서는 java.util.concurrent 패키지를 제공하여 동시성을 지원하고 있다. 이는 executors와 concurrent collections, synchronizers, timing 유틸리티를 포함하고 있다.

Executor 

ThreadPoolExecutor과 같이 ScheduledThreadPoolExecutor 은 Executor을 구현한 인터페이스이다. 이는 설정 가능하고, 유동적인 스레드 풀을 제공한다.
스레드 풀은 스레드의 재사용 가능하도록 해준다.

Executors는 팩토리를 제공한다.  다음은 스레드 풀을 생성하기 위한 내용을 보여준다.

newCachedThreadPool()
    - unbounded 스레드 풀을 생성하며, 자동적으로 재 사용 가능한 스레드이다.

newFixedThreadPool(int nThreads)
    - 고정 크기의 스레드 풀을 생성한다. 이것은 공유된 unbounded 큐를 끈 스레드를 재사용 하도록 한다.

newScheduledThreadPool(int corePoolSize)
    - 스레드 풀을 생성하며, 스케줄 된 커맨드를 가진 주기적인 실행 혹은 지정된 딜레이를 가진 스레드 풀을 지원한다.

newSingleThreadExecutor()
    - 단일 스레드 executor을 생성하고, unbounded 큐를 끈 처리를 수행한다.

newSingleThreadScheduledExecutor()
    - 단일 스레드 executor을 생성하고 지정된 기간 혹은 특정 딜레이에 의한 스케줄된 커맨드를 가질 수 있다.

다음은 newFixedThreadPool 팩토리 메소드를 사용한 예제이다.

import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
public class ThreadPoolExecutor {
    public static void main() {
        // 태스크를 생성한다.
        RTask t1 = new RTask("thread1");
        RTask t2 = new RTask("thread2");
        // 스레드 매니저를 생성한다.
        ExecutorService threadExecutor = Executors.newFixedThreadPool(2);
        // 스레드를 실행 가능 상태로 만든다.
        threadExecutor.execute(t1);
        threadExecutor.execute(t2);
        // 스레드를 셧다운 한다.
        threadExecutor.shutdown();
    }
}

Concurrent Collections

컬렉션 타입을 동기화된 방식으로 제공한다. 이는 thread-safe 한 처리를 지원한다.

HashMap <--> ConcurrentHashMap
TreeMap <--> ConcurrentSkipListMap
TreeSet   <--> ConcurrentSkipListSet
Map subtypes <--> ConcurrentMap
List subtypes <--> CopyOnWriteArrayList
Set subtypes  <--> CopyOnWriteArraySet
PriorityQueue <--> PriorityBlockingQueue
Deque            <--> BlockingDequeue
Queue            <--> BlockingQueue


Synchronizers

Synchronizers는 특별한 목적을 위해 만들어진 동기화 툴이다.
Semaphore : 허가들의 집합을 관리한다.
CountDownLatch : 막 수행된 오퍼레이션의 집합에 대한 waits를 구현한다.
CyclicBarrer : 공통 장벽 지점에 대한 waits를 구현한다.
Exchanger : 동기화 포인트를 구현하며, 스레드들이 변화시킬 수 있는 엘리먼트에 구현한다.


Timing Utility

TimeUnit은 enumeration으로 시간 기반의 메소드에 공통으로 사용된다. 이것은 시간 파라미터가 어떤 단위로 진행될지 지정하며, 다음과 같다.

if (lock.tryLock(15L, TimeUnit.DAYS)) {...} // 15일 락을 시도한다.

NANOSECONDS : 1/1000us 나노초
MICROSECONDS : 1/1000ms 마이크로초
MILLISECONDS : 1/1000sec 밀리초
SECONDS : sec : 초
MINUTES : 60sec : 60초
HOURS : 60min : 3600초
DAYS : 24hr : 86400초


from : java 8 pocket book







Share this

Related Posts

Previous
Next Post »