on
JAVA / 자바 Thread
JAVA / 자바 Thread
프로그램
소스코드로 잘 짜여진 틀,
실행이 안 된 상태
프로세스
실행된 프로그램
운영체제로부터 시스템 자원을 할당받는 작업의 단위
JAVA는 운영체제가 바로 실행시켜주지 않고 JVM에 의해 실행되기 때문에
JVM으로부터 시스템 자원을 할당받는다.
쓰레드 (=처리 경로)
프로세스 처리 경로
멀티쓰레드를 구현할 때에는 스케줄링 작업이 필요하다.
- 단일 쓰레드
처리 경로를 한 개만 가지고 있기 때문에 직렬적이다.
동시에 많은 양을 처리하기 힘들기 때문에 상대적으로 비효율적이다.
하지만 하나의 작업에 문제가 발생하더라도 다른 작업에는 영향을 끼치지 않는다.
따라서 안정성이 보장되고 설계 시 멀티 쓰레드에 비해 쉬다.
- 멀티 쓰레드
하나의 프로세스를 동시에 처리하는 것처럼 보이지만 사실은 매우 짧은 단위로 분할해서 차례로 처리한다.
여러 개의 처리 경로를 가질 수 있도록 하며, 동시 작업이 가능해진다.
설계하기 굉장히 어려우며, 하나의 쓰레드 문제 발생 시 모든 쓰레드에 문제가 발생하게 된다.
JAVA 웹 서버가 대표적인 멀티 쓰레드이다. 멀티 쓰레드로 설계했다면, 처리량 증가, 효율성 증가,
처리비용 감소의 장점이 있기 때문에 단점을 감수하고 설계하는 편이다.
※ 최대 단점 : 교착상태(DeadLock)
멀티 쓰레드 중 쓰레드 간에 대기 상태가 종료되지 않아서 무한정 대기만 하는 비정상적인 상태
교착상태인지를 판단했다면 전체 쓰레드를 깨워주거나, 하나의 쓰레드를 종료시켜주면 교착상태가 해결
멀티 쓰레드 구현 방법
※ 핵심 : run()메소드 재정의
1. Thread 클래스 상속 (extends를 쓸것인가)
2. Runnable 인터페이스 지정 (implement를 쓸것인가, 이 방법을 선호)
[실습]
Thread1, Thread2, Thread3은 항상 순서대로 실행된다.
출력 시 반드시 위의 순서를 지켜서 출력되어야 한다.
입력 예)
1 3 2
출력 예)
1번 쓰레드 : first
2번 쓰레드 : third
3번 쓰레드 : second
※ 람다식을 최소 3번 사용한다.
ThreadTask 클래스
package thread.threadtest2; public class ThreadTask implements Runnable{ public static int cnt; public ThreadTask() {;} public void printFirst(Runnable first) { first.run(); //수정 금지 } public void printSecond(Runnable second) { second.run(); //수정 금지 } public void printThird(Runnable third) { third.run(); //수정 금지 } @Override public void run() { switch(Thread.currentThread().getName()) { case "1": printFirst( () -> System.out.println(++cnt + "번 쓰레드 : first")); break; case "2": printSecond( () -> System.out.println(++cnt + "번 쓰레드 : second")); break; case "3": printThird( () -> System.out.println(++cnt + "번 쓰레드 : third")); break; } } }
ThreadMain 클래스
package thread.threadtest2; import java.util.Scanner; public class ThreadMain { public static void main(String[] args) { Scanner sc = new Scanner(System.in); //사용자가 입력한 정수를 담을 배열 int[] arInput = new int[3]; //Thread1, Thread2, Thread2 Thread[] arThread = new Thread[3]; //run이 구현된 객체 ThreadTask tt = new ThreadTask(); for (int i = 0; i < arThread.length; i++) { //tt를 전달하여 스케줄링 준비를 한다. arThread[i] = new Thread(tt); } System.out.println("입력 : "); for (int i = 0; i < arInput.length; i++) { arInput[i] = sc.nextInt(); //각 쓰레드의 이름은 사용자가 입력한 정수로 설정 arThread[i].setName(arInput[i] + ""); } for (int i = 0; i < arThread.length; i++) { //하나씩 순서대로 실행되어야 하니까 join을 매번 사용해준다 arThread[i].start(); try{ arThread[i].join(); } catch (InterruptedException e) {;} } } }
from http://lyrical-hyun.tistory.com/30 by ccl(A) rewrite - 2021-12-19 23:01:33