[TIL] 스레드와 동시성 (24.01.18 - 25일차)

배고픈 배극곰·2024년 1월 18일
0
post-custom-banner

보편적으로 task들은 각각 서로에 대해 독립적으로 작용하지만, 몇몇은 외부의 실행에 의해 의존적으로 실행되기도 한다.

Threads
즉, 스레드는 유사성을 가진 모든 수행문을 동시에 실행하도록 해준다.

외부서비스나 데이터 저장소로부터 데이터 입력을 기다리며 지속해서 다른 task에 대한 정보를 얻을 수 있기 때문.

public class ThreadBasicsRunner {
    public static void main(String[] args) {
        //Task1 - 101 to 199
        for(int i=101; i<=199; i++)
            System.out.print(i + " ");
        System.out.print("\n Task1 Done");

        //Task2
        for (int i=201; i<=299; i++)
            System.out.print(i + " ");
        System.out.print("\n Task2 Done");

        //Task3
        for (int i=301; i<=399; i++)
            System.out.print(i + " ");
        System.out.print("\n Task3 Done");
    }
}

Thread 직접 만들기

방법 1. Thread 클래스 확장

class Task1 extends Thread {
    public void run() {
        System.out.print("\nTask1 Started");
        for(int i=101; i<=199; i++)
            System.out.print(i + " ");
        System.out.print("\nTask1 Done");
    }
}

방법 2. Runnable 인터페이스 실행

class Task2 implements Runnable {
    @Override
    public void run() {
        System.out.print("\nTask2 Started");
        for(int i=201; i<=299; i++)
            System.out.print(i + " ");
        System.out.print("\nTask2 Done");
    }
}

public class ThreadBasicsRunner {
    public static void main(String[] args) {
    	// ...나머지 코드
        
		System.out.print("\nTask2 Kicked Off");
		Task2 task2 = new Task2();
		Thread task2Thread = new Thread(task2);
		task2Thread.start();
    }
}

=> 그림에서 나온 결과처럼 스레드를 사용하면,
각각의 TASK를 처리하면서 처리 중간중간에 cpu가 대기할때 또 다른일을 수행하도록.
즉, 병렬적으로 작업을 수행할 수 있다는 장점이있다.

스레드 장점

  1. 성능 향상
  2. 자원 공유 효율성 향상
    ★3. 동시성 (동시에 실행될수있다. 작업 병렬 처리)
  3. 간결성
    -> 작업 분리할 수 있어서 코드가 간결

스레드 단점

  1. 스레드간 상호간섭
  2. 많이 생성하면 성능저하 (스레드 많으면 컨텍스트 스위칭이 빈번하게 발생하므로)
    ★3. 동기화 이슈
    => 여러 스레드가 공유 자원에 동시에 접근할때, 동기화 문제가 발생할 수 있음.
    => Race Condition (경쟁 상태)
  3. 메모리 사용량 문제

스레드의 상태

● NEW;
● RUNNABLE;
● RUNNING;
● BLOCKED/WAITING;
● TERMINATED/DEAD;

스레드에서 우선순위 부여하는 방법 (스레드 스케줄링)

  1. 우선순위 방식 (priority)
    => 우선순위가 높은 스레드가 실행상태를 더 많이 가지도록 하는 기법 (setPriority() 사용)

  2. 순환할당 방식 (Round-Robin)
    => Time Slice(시간 할당량) 를 정해서 하나의 스레드를 정해진 시간만큼 실행하고 다른스레드를 실행하는 방식
    => JVM에의 결정되므로 개발자의 임의적인 수정이 불가.

우선순위방식으로 실습해보았다.

🔢 setPriority()메서드
클수록 우선순위가 높은 것이 되는것이고,
우선순위 범위는 MAX_PRIORITY ~ MIN_PRIORITY 사이에 존재해야한다.
=> thread의 기본 우선순위는 NORM_PRIORITY의 값 5이다.

MIN_PRIORITY => 1
MAX_PRIORITY => 10

우선순위가 높다고 반드시 수행되는 것이 아닌, 해당 스레드가 수행될 빈도수를 높여주는 것이다!
=> 추천을 해주는 것이다고 한다.

✔️join() 메서드
task1.join() 을 사용하면 해당 task가 끝났을 경우에야 다음 코드로 실행이 넘어간다.
즉, join()을 활용해서 특정 thread의 실행이 끝날때까지 나머지 스레드를 대기 시킬수있다.

퀴즈


  1. Java에서 runnable 인터페이스를 구현하는 목적은?
    -> 스레드에 의해 실행될 수 있는 클래스를 생성함.

  2. Java에서 스레드 우선순위 범위
    -> 1 to 10

  3. join()메서드 목적?
    -> 다른 스레드가 완료될때까지 스레드가 대기할 수 있도록 하기위함.

  4. 스레드 관리를 위해, Thread 클래스 또는 Runnable 인터페이스를 사용하면 어떤 단점이 있습니까?
    -> 스레드 실행 자세히 제어못함, 다수의 스레드 관리시 유지 어려움, 서브 태스크에서 결과받을방법X

  5. 하나의 스레드로 ExecutorService 생성하는데 사용하는 메서드
    -> ExecutorService.newSingleThreadExecutor()

  6. 지정된 개수의 스레드로 스레드풀 만드는 메서드?
    -> ExecutorService.newFixedThreadPool()

  7. 스레드 풀에 있는 스레드의 개수보다 많은 태스크가 ExecutorService에 제출되면 어떤 일이 일어납니까?
    -> 추가적인 태스크는 대기열로 가고 스레드를 사용할수있게 되면 실행.

  8. 결과를 리턴하는 서브 태스크 생성하기 위해 사용하는 인터페이스?
    -> Callable

  9. Callable 태스크 컬렉션으로부터 가장 빠른 완성된 태스크의 결과를 기다리는 데 사용할 수 있는 ExecutorService의 메서드는?
    -> invokeAny()

profile
마부작침 형설지공
post-custom-banner

0개의 댓글