classThreadWithRunnableimplementsRunnable{publicvoidrun(){for(inti=0;i<5;i++){System.out.println(Thread.currentThread().getName());// 현재 실행 중인 스레드의 이름을 반환try{Thread.sleep(10);}catch(InterruptedExceptione){e.printStackTrace();}}}}Threadthread=newThread(newThreadWithRunnable());//Runnable 인터페이스를 구현하는 방법thread.start();//스레드의 실행
Thread 클래스를 상속받는 방법
classThreadWithClassextendsThread{publicvoidrun(){for(inti=0;i<5;i++){System.out.println(getName());//현재 실행 중인 스레드의 이름을 반환함.try{Thread.sleep(10);//0.01초간 스레드를 정지 (단위 : 1/1000초)}catch(InterruptedExceptione){e.printStackTrace();}}}}ThreadWithClassthread=newThreadWithClass();//Thread 클래스를 상속받는 방법thread.start();//스레드의 실행
스레드의 우선순위
Java에서 각 스레드는 우선순위(priority)에 관한 자신만의 필드를 가지고 있다.
우선순위에 따라 특정 스레드가 더 많은 시간 동안 작업을 할 수 있도록 설정할 수 있다.
getPriority()와 setPriority() 메소드를 통해 스레드의 우선순위를 반환하거나 변경할 수 있다.
스레드의 우선순위가 가질 수 있는 범위
1 ~ 10
숫자가 높을수록 우선순위가 높아진다.
스레드의 우선순위는 비례적인 절댓값이 아닌 어디까지나 상대적인 값이다.
우선순위가 10인 스레드가 우선순위가 1인 스레드보다 10배 더 빨리 수행되는 것이 아니다.
우선순위가 높은 스레드는 우선순위가 낮은 스레드보다 좀 더 많이 실행 큐에 포함되어, 좀 더 많은 작업 시간을 할당받을 뿐이다.
스레드의 우선순위는 해당 스레드를 생성한 스레드의 우선순위를 상속받게 된다.
기본값 : 5
필드
설명
static int MAX_PRIORITY
스레드가 가질 수 있는 최대 우선순위를 명시
static int MIN_PRIORITY
스레드가 가질 수 있는 최소 우선순위를 명시
static int NORM_PRIORITY
스레드가 생성될 때 가지는 기본 우선순위를 명시
사용 예시
classThreadWithRunnableimplementsRunnable{publicvoidrun(){for(inti=0;i<5;i++){System.out.println(Thread.currentThread().getName());// 현재 실행 중인 스레드의 이름을 반환함.try{Thread.sleep(10);}catch(InterruptedExceptione){e.printStackTrace();}}}}//s:메인Threadthread1=newThread(newThreadWithRunnable());Threadthread2=newThread(newThreadWithRunnable());thread2.setPriority(10);// Thread-1의 우선순위를 10으로 변경함.thread1.start();// Thread-0 실행thread2.start();// Thread-1 실행System.out.println(thread1.getPriority());System.out.println(thread2.getPriority());//e:메인
멀티 스레드(multi thread)
멀티 스레드 (multi thread)
하나의 프로세스 내에서 둘 이상의 스레드가 동시에 작업을 수행하는 것
멀티 프로세스 (multi process)
여러 개의 CPU를 사용하여 여러 프로세스를 동시에 수행하는 것
공통점
여러 흐름을 동시에 수행한다.
차이점
멀티 프로세스
각 프로세스가 독립적인 메모리를 가지고 별도로 실행된다.
멀티 스레드
각 스레드가 자신이 속한 프로세스의 메모리를 공유한다.
문맥 교환 (context switching)
현재까지의 작업 상태나 다음 작업에 필요한 각종 데이터를 저장하고 읽어오는 작업
CPU의 코어 수보다 더 많은 스레드가 실행되면, 각 코어가 정해진 시간동안 여러 작업을 번갈아가며 수행하는데 이 때 각 스레드가 서로 교체될 때 스레드 간의 문맥 교환이 발생한다.
컴퓨터에서 동시에 처리할 수 있는 최대 작업 수는 CPU의 코어 수와 같다.
문맥 교환에 걸리는 시간이 커지면 커질수록, 멀티 스레딩의 효율은 저하된다.
많은 양의 단순한 계산은 싱글 스레드로 동작하는 것이 더 효율적일 수 있다.
많은 수의 스레드를 실행하는 것이 언제나 좋은 성능을 보이는 것은 아니다.
멀티 스레드는 각 스레드가 자신이 속한 프로세스의 메모리를 공유하므로 시스템 자원의 낭비가 적다.
하나의 스레드가 작업을 할 때 다른 스레드가 별도의 작업을 할 수 있어 사용자와의 응답성도 좋아진다.
스레드 그룹 (thread group)
서로 관련이 있는 스레드를 하나의 그룹으로 묶어 다루기 위한 장치
Java에서는 스레드 그룹을 다루기 위해 ThreadGroup이라는 클래스를 제공한다.
스레드 그룹은 다른 스레드 그룹을 포함할 수도 있다.
포함된 스레드 그룹은 트리 형태로 연결된다.
스레드는 자신이 포함된 스레드 그룹이나 그 하위 그룹에는 접근할 수 있지만 다른 그룹에는 접근할 수 없다.
스레드 그룹은 스레드가 접근할 수 있는 범위를 제한하는 보안상으로도 중요한 역할을 하고 있다.
사용 예시
classThreadWithRunnableimplementsRunnable{publicvoidrun(){try{Thread.sleep(10);//0.01초간 스레드를 멈춤.}catch(InterruptedExceptione){e.printStackTrace();}}}//s:메인Threadthread0=newThread(newThreadWithRunnable());thread0.start();//Thread-0 실행System.out.println(thread0.getThreadGroup());//main이라는 스레드 그룹에 속해있다고 출력된다.ThreadGroupgroup=newThreadGroup("myThread");//myThread라는 스레드 그룹 생성group.setMaxPriority(7);//해당 스레드 그룹의 최대 우선순위를 7로 설정//스레드를 생성할 때 포함될 스레드 그룹을 전달할 수 있다.Threadthread1=newThread(group,newThreadWithRunnable());thread1.start();//Thread-1 실행System.out.println(thread1.getThreadGroup());//e:메인
데몬 스레드 (deamon thread)
다른 일반 스레드의 작업을 돕는 보조 스레드
일반 스레드가 모두 종료되면 할 일이 때문에 자동으로 종료된다.
일정 시간마다 자동으로 수행되는 저장 및 화면 갱신 등에 이용된다.
사용 예시
classThreadWithRunnableimplementsRunnable{publicvoidrun(){//데몬 스레드인지 확인if(Thread.currentThread().isDaemon()){while(true){try{Thread.sleep(100L);System.out.println("thread is running (type : daemon)");}catch(InterruptedExceptione){e.printStackTrace();}}}else{System.out.println("thread is running (type : normal)");}}}//s:메인Threadt1=newThread(newThreadWithRunnable());Threadt2=newThread(newThreadWithRunnable());t1.setDaemon(true);//t1을 데몬 스레드로 설정t1.start();t2.start();//e:메인
가비지 컬렉터 (gabage collector)
프로그래머가 동적으로 할당한 메모리 중 더 이상 사용하지 않는 영역을 자동으로 찾아내어 해제해 주는 데몬 스레드
데몬 스레드를 이용하는 가장 대표적인 예시
Java에서는 프로그래머가 메모리에 직접 접근하지 못하게 하는 대신에 가비지 컬렉터가 자동으로 메모리를 관리해준다.
이용 시 프로그래밍을 하기가 훨씬 쉬워지며, 메모리에 관련된 버그가 발생할 확률도 낮아진다.