운영체제는 두가지 이상의 작업을 동시에 처리하는 멀티 태스킹을 할 수 있도록 CPU 및 메모리 자원을 프로세스마다 적절히 할당해주고, 병렬로 실행시킴
운영체제에서 할당받은 자신의 메모리를 가지고 실행하기 때문에 각 프로세스는 독립적
→ 하나의 프로세스에서 오류 발생해도 다른 프로세스에 영향 미치지 않음
하나의 프로세스 내부에 생성되기 때문에 하나의 스레드가 예외를 발생시키면 프로세스 자체가 종료될 수 있어 다른 스레드에 영향 미침
Thread 클래스로부터 직접 생성
Thread thread = new Thread(Runnable target);
class Task implements Runnable {
public void run() {
스레드가 실행할 코드;
}
}
Thread thread = new Thread(new Runnable() {
public void run() {
스레드가 실행할 코드;
}
});
thread.start();
import java.awt.Toolkit;
public class BeepPrintExample1 {
public static void main(String[] args) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
for(int i=0; i<5; i++) {
toolkit.beep();
try { Thread.sleep(500); } catch(Exception e) {}
}
for(int i=0; i<5; i++) {
System.out.println("띵");
try { Thread.sleep(500); } catch(Exception e) {}
}
}
}
// 비프음 실행 작업
import java.awt.Toolkit;
public class BeepTask implements Runnable {
public void run() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
for(int i=0; i<5; i++) {
toolkit.beep();
try { Thread.sleep(500); } catch(Exception e) {}
}
}
}
// 메인스레드
public class BeepPrintExample2 {
public static void main(String[] args) {
Runnable beepTask = new BeepTask();
Thread thread = new Thread(beepTask);
thread.start();
for(int i=0; i<5; i++) {
System.out.println("띵");
try { Thread.sleep(500); } catch(Exception e) {}
}
}
}
Thread 하위 클래스로부터 생성
public class WokerThread extends Thread {
@Override
public void run() {
스레드가 실행할 코드;
}
}
Thread thread = new WokerThread();
// 코드 절약 위해 익명 객체로 작업 스레드 생성
Thread thread = new Thread() {
public void run() {
스레드가 실행할 코드;
}
thread.start();
// 비프음 스레드
import java.awt.Toolkit;
public class BeepThread extends Thread {
@Override
public void run() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
for(int i=0; i<5; i++) {
toolkit.beep();
try { Thread.sleep(500); } catch(Exception e) {}
}
}
}
// 실행 코드
public class BeepPrintExample4 {
public static void main(String[] args) {
Thread thread = new BeepThread();
thread.start();
for(int i=0; i<5; i++) {
System.out.println("띵");
try { Thread.sleep(500); } catch(Exception e) {}
}
}
}
스레드 이름
thread.setName(”스레드이름”);
thread.getName();
Thread thread = Thread.currentThread();
public synchronized void method() {
임계영역;
}
메서드 | 설명 |
---|---|
interrupt() | 일시 정지 상태의 스레드에서 InterruptedException을 발생시켜, 예외 처리 코드(catch)에서 실행 대기 상태로 가거나 종료 상태로 갈 수 있도록 합니다. |
sleep(long millis) | 주어진 시간 동안 스레드를 일시 정지 상태로 만듭니다. 주어진 시간이 지나면 자동적으로 실행 대기 상태가 됩니다. |
stop() | 스레드를 즉시 종료합니다. 불안전한 종료를 유발하므로 사용하지 않는 것이 좋습니다. |
주어진 시간 동안 일시 정지
import java.awt.Toolkit;
public class SleepExample {
public static void main(String[] args) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
for(int i=0; i<10; i++) {
toolkit.beep();
try {
Thread.sleep(3000); // 3초 일시정지
} catch(InterruptedException e) {
}
}
}
}
스레드 안전한 종료
스레드는 run()메서드가 끝나면 자동으로 종료되므로, stop 플래그를 이용해서 run()메서드의 종료를 유도
public class XXXThread extends Thread {
private boolean stop; // stop 플래그 필드
public void run() {
while(!stop) {
스레드가 반복 실행하는 코드;
}
// 스레드가 사용한 자원 정리
}
}
stop 필드가 true일 경우 while문을 빠져나오고 스레드가 사용한 자원을 정리
→ run() 메서드가 끝나게 되므로 스레드는 안전하게 종료
interrupt() 메서드는 스레드가 일시정지 상태에 있을 때 InterruptedException을 발생시키는 역할을 함. 이를 이용하면 run()메서드 정상 종료 가능
ThreadA가 ThreadB의 interrupt() 메서드를 실행하게 되면 ThreadB가 sleep() 메서드로 일시 정지 상태가 될 때 ThreadB에서 InterruptedException이 발생하여 예외처리 블록으로 이동
→ ThreadB는 while문 빠져나와 run()메서드 정상 종료
// 1초후 출력 스레드 중지
public class InterruptExample {
public static void main(String[] args) {
Thread thread = new PrintThread();
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
thread.interrupt(); // 1초 후에 멈추도록 interrupt 메서드 호출
}
}
// 무한 반복해서 출력하는 스레드
public class PrintThread extends Thread {
public void run() {
try {
while(true) {
System.out.println("실행 중");
Thread.sleep(1);
}
} catch(InterruptedException e) {}
System.out.println("자원 정리");
System.out.println("실행 종료");
}
}
주목할 점은 스레드가 실행 대기 또는 실행 상태에 있을 때 interrupt() 메서드가 실행되면 즉시 InterruptedException이 발생하지 않고, 스레드가 일지 정지 상태가 되면 발생
따라서 일지 정시 상태가 되지 않으면 interrupt() 메서드 호출은 의미 없음
→ 일시정지 만들기 위해 Thread.sleep(1) 사용
일시정지 만들지 않고 interrupt() 호출
public class PrintThread extends Thread {
public void run() {
while(true) {
System.out.println("실행 중");
if(Thread.interrupted()) { // interrupted 되었는지 확인
break;
}
}
System.out.println("자원 정리");
System.out.println("실행 종료");
}
}
데몬 스레드
public static void main(String[] args) {
AutoSaveThread thread = new AutoSaveThread();
thread.setDaemon(true);
thread.start();
...
} // AutoSaveThread가 데몬이 됨
// 1초 주기로 save() 메서드 호출하는 데몬 스레드
public class AutoSaveThread extends Thread {
public void save() {
System.out.println("작업 내용을 저장함.");
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
save();
}
}
}
// 메인스레드 코드
public class DaemonExample {
public static void main(String[] args) {
AutoSaveThread autoSaveThread = new AutoSaveThread();
autoSaveThread.setDaemon(true);
autoSaveThread.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
System.out.println("메인 스레드 종료");
}
}