[ Thread 스레드 ]
: 프로세스 내의 세부적 실행 단위(사전적 의미는 '실')
⇒ 현재 실행 중인 프로그램의 세부적 실행단위
* process는 현재 실행중인 프로그램을 의미
ex)
예제 1.
동영상 재생 프로그램을 실행(process)한다.
영상서비스, 음향서비스, 자막서비스가 thread 로 동작된다.
예제 2. 클라이언트 프로그램
채팅 클라이언트 프로그램을 실행(process)한다.
→ 채팅 클라이언트 프로세스 내에 필수적인 실행단위는 두 가지이다.
→ 동시에 서비스되어야 하므로 멀티 스레드가 필요하다.
1. 친구들의 메세지를 입력받는 스레드
2. 친구들에게 메세지를 출력하는 스레드
예제 3. 서버 프로그램
채팅 서버 프로그램을 실행(process)한다.
→ 접속한 클라이언트 모두 서비스를 해야한다 : 서비스 내용은 동일
→ 접속한 클라이언트 수만큼 스레드를 각각 만들어 서비스해야 한다.
1. 서비스하는 스레드 수는 다수 (mulit thread)
2. 서비스를 표현하는 클래스는 하나(implement Runnable or extends Thread) (one service)
ex) 실생활 예
BC카드 콜센터에 여러 고객이 동시에 상담한다 → 콜센터 process
콜센터 직원 thread가 고객 당 생성되어 동시에 상담 서비스를 상담한다 → 콜센터 직원 thread(multi thread)
Thread 생성 방법
1) extends Thread
2) implements Runnable
* 자바는 단일 상속이므로, 다중 구현(다양한 계층구조 형성)이 가능한 방법인, 2번 방법을 더 선호한다.
//Thread 작업 내용을 정의하는 클래스
public class InputWorker implements Runnable{
//Runnable interface의 abstract method를 구현한다
@Override
public void run(){
//스레드 실행 내용
}
}
Thread 실행 및 흐름 제어
- start() : thread를 실행 가능 상태로 보낸다. ( jvm이 실행하는 것이지, 개발자가 실행하는 것은 X !! )
jvm이 이후 스케쥴링을하여 선택될 경우 실행상태로 전이된다. - run() : thread의 실행 내용을 정의하는 영역
jvm에 의해 스케쥴링을 받으면 run()이 실행되고 run()메서드 실행이 마치면 Thread는 종료된다.
//위 Thread를 이용해 Thread를 생성하는 코드
InputWorker worker = new InputWorker();
Thread thread = new Thread(worker);
thread.start(); //해당 Thread를 실행가능 상태로 보내고, jvm이 스케쥴링하면 run()실행
단일 스레드 예제
package step1;
//단일 thread 작동
class Worker{
public void work() {
for (int i = 0; i < 5; i++) {
System.out.println(i+1 +"번째 "+"Worker Class의 work method 실행");
}
}
}
public class TestThread1 {
public static void main(String[] args) {
System.out.println("**main thread 시작**");
Worker w = new Worker();
w.work();
System.out.println("**main thread 시작**");
/* 출력값 :
* **main thread 시작**
* 1번째 Worker Class의 work method 실행
* 2번째 Worker Class의 work method 실행
* 3번째 Worker Class의 work method 실행
* 4번째 Worker Class의 work method 실행
* 5번째 Worker Class의 work method 실행
* **main thread 시작**
*/
}
}
* step1 단일스레드 예제와 실행결과를 비교해 본다
Multi Thread 멀티 스레드 예제 1
: extends Thread로 생성
: main 와 WorkerThread 즉 두개의 스레드가 동작되는 예제
package step2;
// multiple thread
class Worker extends Thread{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(i+1 +"번째 "+"Worker Class의 run method 실행");
}
}
}
public class TestThread2 {
public static void main(String[] args) {
System.out.println("***main thread 시작***");
/* Worker Thread 생성 및 실행
* run() 메서드 실행이 아닌,
* start()라는 Thread 클래스 메서드를 실행해야 한다
*/
Worker w = new Worker();
w.start();
System.out.println("***main thread 끝***");
/* 출력값 :
* ***main thread 시작***
* ***main thread 끝***
* 1번째 Worker Class의 run method 실행
* 2번째 Worker Class의 run method 실행
* 3번째 Worker Class의 run method 실행
* 4번째 Worker Class의 run method 실행
* 5번째 Worker Class의 run method 실행
*/
}
}
1. main thread 먼저 동작
2. w.start() → thread를 실행시키는 것이 아니라, 실행 가능하게끔 해줌
3. extends된 Worker 클래스 동작
Multi Thread 멀티 스레드 예제 2 (채팅 클라이언트)
: implements Runnable 로 생성
: 채팅 클라이언트 프로그램을 연상하며 두 개의 스레드를 생성시켜 실행해본다.
1. InputWorker Thread : 친구들의 메세지를 입력받는 일을 하는 thread
2. main Thread - outputMessage() : 친구들에게 메세지를 출력하는 일을 하는 thread
package step3;
class InputWorker implements Runnable{
//jvm에 의해 run이 가장 먼저 자동 호출됨.
@Override
public void run() {
inputMessage();
}
public void inputMessage() {
for (int i = 0; i < 10; i++) {
System.out.println("친구들의 메세지를 입력받는 Input Thread");
}
}
}
public class TestThread3 {
public void outputMessage() {
for (int i = 0; i < 5; i++) {
System.out.println("친구들의 메세지를 출력하는 Output Thread");
}
}
public static void main(String[] args) {
System.out.println("***main thread 시작***");
//implement Runnable한 클래스를 이용해
//thread를 생성하고 start()
InputWorker w = new InputWorker();
Thread thread = new Thread(w);
thread.start();
new TestThread3().outputMessage();
System.out.println("***main thread 종료***");
}
/* 출력값:
* ***main thread 시작***
* 친구들의 메세지를 출력하는 Output Thread
* 친구들의 메세지를 출력하는 Output Thread
* 친구들의 메세지를 출력하는 Output Thread
* 친구들의 메세지를 출력하는 Output Thread
* 친구들의 메세지를 출력하는 Output Thread
* *** main thread 종료***
* 친구들의 메세지를 입력받는 Input Thread
* 친구들의 메세지를 입력받는 Input Thread
* 친구들의 메세지를 입력받는 Input Thread
* 친구들의 메세지를 입력받는 Input Thread
* 친구들의 메세지를 입력받는 Input Thread
* 친구들의 메세지를 입력받는 Input Thread
* 친구들의 메세지를 입력받는 Input Thread
* 친구들의 메세지를 입력받는 Input Thread
* 친구들의 메세지를 입력받는 Input Thread
* 친구들의 메세지를 입력받는 Input Thread
*/
}
< InputWorker Class >
1. InputWorker Thread의 작업 내용을 정의 ← class InputWorker implements Runnable {}
2. JVM이 스케쥴링하면 이 메서드가 자동호출된다. ← @Override public void run() { }
< TestThread3 Class > - main class
3. implement Runnable한 클래스를 이용해 thread를 생성
← InputWorker w = new InputWorker();
← Thread thread = new Thread(w);
4. 해당 Thread의 시작을 함
← thread.start();
5. 친구들의 메세지를 받는 메서드 형성
← public void outputMessage(){}
6. outputMessage 실행 : main thread 종료 전에 반드시 수행됨 -- main thread 영역에 있기때문
← new TestThread3().outputMessage()
Multi Thread 멀티 스레드 예제 3 (동영상)
: implements Runnable 로 생성
: 동영상 플레이어 프로세스로 가정
1. VideoWorker 영상 작업 스레드
2. AudioWorker 음향 작업 스레드
package step4;
class VideoWorker implements Runnable {
@Override
public void run() {
try {
work();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void work() throws InterruptedException {
for (int i = 0; i < 5; i++) {
System.out.println("영상 작업 Thread(VideoWorker): " + i);
Thread.sleep(1000); // 1초간 스레드 작업 일시 중단 후 재개
}
}
}
class AudioWorker implements Runnable {
@Override
public void run() {
try {
work();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
public void work() throws InterruptedException {
for (int i = 0; i < 5; i++) {
System.out.println("음향 작업 Thread(AudioWorker): "+ i);
Thread.sleep(1000);
}
}
}
public class TestThread4 {
public static void main(String[] args) {
System.out.println("***main thread 시작***");
new Thread(new VideoWorker()).start();
new Thread(new AudioWorker()).start();
System.out.println("***main thread 종료***");
/* 출력값:
* ***main thread 시작***
* 영상 작업 Thread(VideoWorker): 0
* *** main thread 종료***
* 음향 작업 Thread(AudioWorker): 0
* 영상 작업 Thread(VideoWorker): 1
* 음향 작업 Thread(AudioWorker): 1
* 음향 작업 Thread(AudioWorker): 2
* 영상 작업 Thread(VideoWorker): 2
* 음향 작업 Thread(AudioWorker): 3
* 영상 작업 Thread(VideoWorker): 3
* 음향 작업 Thread(AudioWorker): 4
* 영상 작업 Thread(VideoWorker): 4
*/
}
}
메인 스레드와는 무관하게 동작하며,
VideoWorker thread와 AudioWorker thread는 동시작업된다.
Web Server 에서의 thread
> 다수의 client를 상대하기 위해서는 각자의 다양한 thread가 필요하다.
Multi Thread 멀티 스레드 예제 4 (채팅 서버)
: 하나의 클래스를 이용해 다수의 스레드를 생성해서 실행하는 예제
: 채팅 서버를 가정하고 서비스 내용은 동일하나, 접속한 다수의 클라이언트에게 동시에 서비스하기 위해
다수의 스레드를 생성하여 실행하도록 구현해본다.
package step5;
//채팅 서비스를 제공하는 클래스
class ServerWorker implements Runnable{
@Override
public void run() {
try {
work();
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
public void work() throws InterruptedException {
//현재 실행중인 스레드의 이름을 반환받는다.
String name = Thread.currentThread().getName();
for (int i = 0; i < 5; i++) {
System.out.println(name + " 고객님에게 채팅 서비스 제공 Thread: "+ i);
Thread.sleep(1000);
}
}
}
// 실행 class
public class TestThread5 {
public static void main(String[] args) {
//Thread 2개 동작 중
//1. Main Thread
//2. ServerWorker Thread
System.out.println("***Main Thread 시작***");
ServerWorker worker = new ServerWorker();
//ServerWorker Thread 1
Thread t1 = new Thread(worker, "앨리사");
t1.start();
//ServerWorket Thread 2
Thread t2 = new Thread(worker, "윌");
t2.start();
//ServerWorket Thread 3
Thread t3 = new Thread(worker, "일레븐");
t3.start();
System.out.println("***Main Thread 종료***");
/* 출력값:
* ***Main Thread 시작***
* *** Main Thread 종료***
* 윌 고객님에게 채팅 서비스 제공 Thread: 0
* 앨리사 고객님에게 채팅 서비스 제공 Thread: 0
* 일레븐 고객님에게 채팅 서비스 제공 Thread: 0
* 앨리사 고객님에게 채팅 서비스 제공 Thread: 1
* 일레븐 고객님에게 채팅 서비스 제공 Thread: 1
* 윌 고객님에게 채팅 서비스 제공 Thread: 1
* 윌 고객님에게 채팅 서비스 제공 Thread: 2
* 일레븐 고객님에게 채팅 서비스 제공 Thread: 2
* 앨리사 고객님에게 채팅 서비스 제공 Thread: 2
* 일레븐 고객님에게 채팅 서비스 제공 Thread: 3
* 앨리사 고객님에게 채팅 서비스 제공 Thread: 3
* 윌 고객님에게 채팅 서비스 제공 Thread: 3
* 앨리사 고객님에게 채팅 서비스 제공 Thread: 4
* 일레븐 고객님에게 채팅 서비스 제공 Thread: 4
* 윌 고객님에게 채팅 서비스 제공 Thread: 4
*/
}
}
1. Main Thread와 ServerWorker Thread 3개가 동시에 동작하고 있다.
2. ServerWorker Class에서 현재 실행중인 스레드의 이름을 반환받는다.
←String name = Thread.currentThread().getName();
3. 서비스의 내용은 동일하므로, ServerWorker 하나로 다수의 Thread를 생성한다.
* 스레드 생성 시 스레드의 name을 함께 할당한다.
← Thread t1 = new Thread(worker, "앨리사");
← Thread t2 = new Thread(worker, "윌");
← Thread t3 = new Thread(worker, "일레븐");
4. start 하여 동작시킨다.
← t1.start();
← t2.start();
← t3.start();
Thread Scheduling
: 자바 스레드 스케쥴링은 우선순위 방식을 채택한다.
thread priority(스레드 우선순위)는 가장 낮은 1부터 가장 높은 10까지 이며,
우선순위를 따로 지정하지 않았을 경우 기본 우선순위인 5가 적용된다.
우선순위에 따라 스케쥴링을 받을 가능성이 높아진다.
> CPU가 system에서 동시 수행할 수 있는 thread 수는 제한되어 있다.
이 개수를 넘어서면 우선순위 방식이 적용된다. 우선순위가 높은 스레드가 스케쥴링의 우선권를 가진다.
* 우선순위 상수값
Thread.NORM_PRIORITY : 5 ← 기본 우선 순위
Thread.MIN_PRIORITY : 1 ← 가장 낮은 우선 순위
Thread.MAX_PRIORITY : 10 ← 가장 높은 우선 순위
java thread scheduling 예제
: test Thread를 20개 생성하여, start() 한 후, 그 중 하나의 우선순위를 가장 높게 설정한 다음 결과 확인
package step6;
class Worker implements Runnable{
@Override
public void run() {
// 현재 진행 중인 Thread의 이름을 반환받음
String name = Thread.currentThread().getName();
int priority = Thread.currentThread().getPriority();
for (long l = 0; l < 9000000000L; l++) {}
System.out.println(name+" Thread 실행 완료! 우선 순위:"+priority);
}
}
public class TestThread6 {
public static void main(String[] args) {
System.out.println("**Main Thread 시작**");
Worker worker = new Worker();
/*
* Thread t1 = new Thread(worker, "1번째 일꾼 Thread");
* t1.setPriority(9);
* t1.start();
*/
// 20개의 Thread를 생성하고 start하되, 9번째 Thread의 우선순위는 10으로 할당
for (int i = 1; i < 21; i++) {
Thread t = new Thread(worker, i+"번째 일꾼 Thread");
if (i == 9)
t.setPriority(Thread.MAX_PRIORITY);
System.out.println(i+"번째 일꾼 Thread start!");
t.start();
}
System.out.println("**Main Thread 종료**");
}
}
[결과]
9번째 Thread 일꾼이 가장 먼저 실행된 것을 확인할 수 있다 !
Daemon Thread
: 백그라운드에서 실행되는 Thread. (aka.background Thread)
: 자신이 실행시킨 Thread가 종료되면 함께 종료된다.
ex) 워드 작업 프로그램 실행 시, 백그라운드에서 주기적으로 백업을 하도록 구현하고 이 백업스레드를 setDaemon(true)로 처리하면, 워드 프로그램 종료 시 함께 종료된다.
Daemon Thread 예제
package step7;
//Daemon Thread 예제
/* Thread class 2개 정의
* 1. Word
* 2. BackupWorker
*
* Word Thread 시작 시, BackupWorker Thread가 시작하도록 코드는 구성되어있다.
* Word Thread가 작업종료 되어, 해당 Thread가 종료되면 함께 BackupWorker Thread가 종료되도록
* setDaemon(true)를 설정한다.
*/
class BackupWorker implements Runnable {
@Override
public void run() {
while (true) {
try {
backup();
Thread.sleep(3000); // 3초마다 백업처리
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void backup() {
System.out.println("문서 백업 처리");
}
}
// Word Thread가 실핼될 때, 사장 먼저 BackupWorker Thread를 생성하여 start 시킨다.
class Word implements Runnable {
@Override
public void run() {
BackupWorker b = new BackupWorker();
Thread backupThread = new Thread(b);
// Word Thread가 종료되면, BackupThread도 함께 종료되도록 설정한다.:setDaemon(true)
backupThread.setDaemon(true);
backupThread.start();
for (int i = 0; i < 10; i++) {
System.out.println("문서 작업 " + i);
try {
Thread.sleep(1000); // 1초마다 문서 작업
} catch (InterruptedException e) {
e.printStackTrace();
} // catch
} // for
System.out.println("**문서 작업 종료**");
}// run
}// Word class
public class TestThread7 {
public static void main(String[] args) {
System.out.println("**Main Thread 시작**");
// 워드 작업 스레드 생성 start
new Thread(new Word()).start();
System.out.println("**Main Thread 종료**");
}
}
1. Word Thread가 실핼될 때, 사장 먼저 BackupWorker Thread를 생성하여 start 시킨다.
← Thread backupThread = new Thread(new BackupWorker());
← backupThread.start();
2. Word Thread가 작업종료 되어, 해당 Thread가 종료되면
함께 BackupWorker Thread가 종료되도록 setDaemon(true)를 설정한다.
← backupThread.setDaemon(true);
[ 결과 ]
[ Synchronized 동기화 ]
: 공유 자원에 대한 Thread의 동시 접근을 막기 위하여 순차적으로 처리하도록 명시하는 것
- java의 Thread는 multi threading 시, multi-Thread를 통해 데이터를 공유할 수 있는 장점이 있다. (공유 자원)
→ 이를 이용해, 다수의 Thread를 생성하고,
실행 시 한번 만든 Thread 객체의 자원을 Heap memory 영역에 하나로 저장되어, 공유할 수 있다.
( 서버의 메모리를 효율적으로 사용한다 ) - 하지만 이 장점이 문제가 될 수 있다. 이럴 경우 synchronized 처리를 통해 해결할 수 있다.
- synchronized (동기화) 처리란 ?
공유자원 영역을 순차적 처리를 하도록 명시하는 것을 의미한다.
* 순차적 처리란 그 영역을 단일 스레드 환경으로 실행하는 것
→ 멀티 스레딩 시 공유자원의 안정성을 위해 사용한다.
→ 여러 스레드는 데이터를 공유해 사용할 수 있고, 이런 면은 스레드 방식의 큰 장점이지만 주의해야 될 사항이 있다. 데이터 자원의 데이터 조작 시 발생할 수 있는 문제에 대비하기 위해 데이터 조작영역을 단일 스레드 환경으로 만드는 synchronized가 필요하다.
[ synchronized의 주요 method ]
- wait() : 특정 조건이 될 경우 현재 실행되는 스레드를 wait pool에 대기시킬 때 사용하는 메서드
- notify() or notifyAll() : 특정 조건이 될 경우 스레드를 wait pool에서 벗어나 object lock pool 상태로 보내는 메서드
*참고 : object lock pool이란 synchronized 처리된 영역에 다른 스레드가 실행 중인 경우 대기하는 pool
+ java se API 중 동기화처리(thread-safe)에 대한 정리
[ Collection 계열 자료구조]
동기화처리(thread-safe)가 되어있는 대표적인 자료 구조
→ Vector, Hashtable
동기화처리가 되어있지 않은 자료구조
→ ArrayList, HashMap
하지만 최근에는 성능상의 이유로 Vector, Hashtable 는 거의 이용하지 않으며,
java.util.Collections의 static method의 synchronizedList() or synchronizedMap()을 이용해
thread-safe(동기화처리)한 컬렉션을 필요시 생성해 사용한다.
[ 문자열 ]
- String : 문자열 변경 시, 문자열 자체는 변하지 않는다
- literal pool(문자열 상수영역)에 저장하고 공유해서 사용 (자원을 아끼기 위해서)
- 문자열을 수정하면, 새로운 문자열을 만든다. - String Builder : 문자열 변경 시, 문자열 자체가 변경된다.
- 문자열을 자주 수정할 때, 사용한다.
- 동기화를 처리가 되어있지 않다. - String Buffer : String Builder와 마찬가지로, 문자열 변경 시 문자열 자체가 변경된다.
- 동기화처리가 되어 있다. (thread - safe)
multi-Thread를 통한 데이터 공유 예시
→ 자바 멀티 스레드는 데이터를 공유할 수 있는 장점을 가진다
class Worker implements Runnable {
private String info = "공유자원";
@Override
public void run() {
String name = Thread.currentThread().getName();
for (int i = 0; i < 3; i++) {
System.out.println(name + " " + info + " 사용하여 작업수행");
try {
Thread.sleep(500); // 0.5초 단위로 thread 실행
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class TestThread9 {
public static void main(String[] args) {
System.out.println("***Main Thread 시작***");
Worker w = new Worker(); // Thread Object인 w가 공유자원으로 사용되고 있다
Thread t1 = new Thread(w, "첫번째 Thread");
Thread t2 = new Thread(w, "두번째 Thread");
Thread t3 = new Thread(w, "세번째 Thread");
t1.start();
t2.start();
t3.start();
System.out.println("***Main Thread 종료***");
/* 출력값:
* ***Main Thread 시작***
* ***Main Thread 종료***
* 첫번째 Thread 공유자원 사용하여 작업수행
* 두번째 Thread 공유자원 사용하여 작업수행
* 세번째 Thread 공유자원 사용하여 작업수행
* 두번째 Thread 공유자원 사용하여 작업수행
* 세번째 Thread 공유자원 사용하여 작업수행
* 첫번째 Thread 공유자원 사용하여 작업수행
* 첫번째 Thread 공유자원 사용하여 작업수행
* 두번째 Thread 공유자원 사용하여 작업수행
* 세번째 Thread 공유자원 사용하여 작업수행
*/
}
}
> 공유자원을 사용할 때, 삽입(insert) / 삭제(delete) 시에는 유의해서 사용해야 한다.
Thread 별로 Stack에서 각각의 메모리로 생성된다.
(main Thread, Thread t1, Thread t2, Thread t3 다 다른 Stack memory에 존재)
이 때, Synchronized를 통해 동시 접근(공유)를 막을 수 있다.
생성 방법
- synchronized 함수를 만들어 사용한다
- synchronized block을 사용한다 → 예제에서는 이 방법을 사용했다
Synchronized 필요성을 확인하는 예제 (문제발생)
→ 하나의 자원에 다수의 Thread가 실행되어 자원을 조작하는 경우, 발생할 수 있는 문제점을 확인하는 예제
class Toilet implements Runnable{
// instance 변수 : 각 Thread의 공유자원
private boolean seat; //instance 변수의 기본초기화 : false 할당
@Override
public void run() {
try {
//use 메서드는 String user가 매개변수로 들어와야 하기 때문에,
//현재 thread의 이름을 user값으로 넣어준다.
use(Thread.currentThread().getName());
} catch(InterruptedException e) {
e.printStackTrace();
}
}
public void use(String user) throws InterruptedException {
if (seat == false) { //seat이 비어있으면 사용가능
Thread.sleep(1000);
seat = true; // 들어가기 전, seat을 true로 채워준다. (사용불가능)
System.out.println(user + " 입장");
System.out.println(user + " 사용");
Thread.sleep(3000);
System.out.println(user + " 퇴장");
seat = false; //퇴장 후, seat을 다시 비워줌 (사용가능)
} else { //seat가 true이면 화장실을 사용하는 상태이므로 입장불가
System.out.println(user + "님이 화장실 사용중이므로 입장불가");
}
}
}
public class TestSynchronizedEx {
public static void main(String[] args) {
Toilet toilet = new Toilet();
Thread t1 = new Thread(toilet, "멜리사 Thread");
Thread t2 = new Thread(toilet, "크리스타 Thread");
t1.start();
t2.start();
}
}
(수정 전) multi-threading 시, 데이터를 공유할 때 일어날 수 있는 문제
Synchronized 를 이용하여 문제를 해결한 예제 (해결)
→ 해결방안 : 공유자원 ( Toilet의 seat ) 에 접근한 영역을 synchronized 처리하면 된다.
class Toilet implements Runnable {
// instance 변수 : 각 Thread의 공유자원
private boolean seat; // instance 변수의 기본초기화 : false 할당
@Override
public void run() {
try {
// use 메서드는 String user가 매개변수로 들어와야 하기 때문에,
// 현재 thread의 이름을 user값으로 넣어준다.
use(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// !! use() method를 synchronized 처리해준다 !!
public synchronized void use(String user) throws InterruptedException {
System.out.println(user + " 입장");
System.out.println(user + " 사용");
System.out.println(user + " 퇴장");
}
}
public class TestSynchronizedSolution {
public static void main(String[] args) {
Toilet toilet = new Toilet();
Thread t1 = new Thread(toilet, "멜리사 Thread");
Thread t2 = new Thread(toilet, "크리스타 Thread");
t1.start();
t2.start();
}
}
(수정 후) 단일 Thread화되어 Thread가 순차적으로 실행이 된다.
자바의 Thread 클래스의 주요 메소드
- run(): 쓰레드의 실질적인 코드 블록입니다.
- setDaemon(): 메인 Thread가 종료되었을 때 자동으로 종료되도록 설정합니다.
- start(): 해당 Thread의 시작을 알리는 함수입니다.
- sleep(long): 주어진 밀리 초(Milli-Second) 동안 쓰레드 작동을 일시정지 합니다. (sleep(1000) = 1초 작업중단)
- interrupt(): Thread를 강제로 종료시킵니다.
- isAlive(): Thread가 살아있는지 물어봅니다.
- join(): 이 Thread가 종료될 때까지 기다린 후에 실행합니다.
- yield(): 실행을 중단하고, 다른 Thread에게 CPU 자원을 양보합니다.