Error : 더 이상 프로그램이 지속될 수 없는 오류
Exception : 해결 가능한 오류
프로그램이 실행되다 중단(error)되면 JVM이 현재 오류 사항에 대한 정보를 모아 (Exception)instance를 생성한다.
이 객체를 우리가 프로그램적으로 처리
try {
} catch {
} finally {
}
독립적인 실행 흐름을 가지고 있다.
프로그램을 실행시키기 위해 OS로부터 resource를 할당받아야 한다.
현재 실행중인 프로그램인 프로세스에는 최소 1개 이상의 thread가 존재
Process = resource + thread
한 순간에 한 가지 일만 수행
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Hello");
}
}
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread();
t.run();
}
}
Call Stack(1개의 thread)
1) main()
2) run()
run()을 직접 실행했기 때문에 별개로 실행되는 method가 아님
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Hello");
}
}
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
}
}
main thread의 call stack
1) main()
2) start() -> t thread의 call stack 생성
t thread의 call stack
3) run()
4) start() 종료
5) main()과 run()이 별개의 thread에서 실행됨
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Hello");
}
}
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
System.out.println("안녕하세요!");
}
}
'Hello'와 '안녕하세요'가 출력되는 순서가 보장되지 않음
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Hello");
}
}
class MyThread2 implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
}
}
Runnable의 run()은 Runnable이 interface이므로 추상 메서드가 되기 때문에 필수적으로 override 해야 하지만 Thread의 run()은 상속받은 메서드이므로 override 선택 가능하다.
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Hello");
}
}
class MyThread2 implements Runnable {
@Override
public void run() {
System.out.println("이 또한 실행 가능!");
}
}
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
MyThread2 a = new MyThread2();
Thread t1 = new Thread(a);
t1.start();
System.out.println("안녕하세요!");
}
}
Runnable interface를 구현한 class의 instance를 생성하여 Thread instance의 생성자로 전달하여 Thread 생성!
new : Thread 객체 생성
객체.start()
Runnable : 실행 가능한 상태 (CPU에 의해 선택됨)로 대기
Thread Scheduler가 Runnable 상태의 Thread들 중 하나를 선택(알고리즘, 자료구조를 이용) -> Running(CPU 점유)
run() 수행
Thread의 run()이 종료
내부에서 파생된 모든 user define thread가 종료되는 순간
t1.setDaemon(true);
public class ThreadExam02 implements Runnable {
static boolean autoSave = false;
public static void main(String[] args) {
Thread t = new Thread(new ThreadExam02());
t.setDaemon(true);
// main thread에서 생성된 daemon thread는 main thread가 종료되면 함께 종료됨
// daemon thread로 지정되어 있지 않으면 무한반복됨 (thread가 종료되지 않기 때문)
t.start(); // main thread, t thread가 시작됨
for(int i = 0; i < 10; i++) {
try {
Thread.sleep(1000); // static method "sleep()" : main thread를 재움
} catch (Exception e) {
}
System.out.println(i);
if(i == 5) {
autoSave = true;
}
}
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(3000); // 해당 코드를 수행하는 thread를 재움
} catch (InterruptedException e) {
}
if(autoSave) {
System.out.println("자동저장 완료");
}
}
}
}
class ThreadExam03_1 extends Thread {
public void run() {
for(int i = 0; i < 300; i++) {
System.out.print("-");
if (i%20 == 0) {
System.out.println();
}
}
System.out.println("<<Thread 1 종료>>");
}
}
class ThreadExam03_2 extends Thread {
@Override
public void run() {
for(int i = 0; i < 300; i++) {
System.out.print("|");
if (i%20 == 0) {
System.out.println();
}
}
System.out.println("<<Thread 2 종료>>");
}
}
public class ThreadExam03 {
public static void main(String[] args) {
ThreadExam03_1 t1 = new ThreadExam03_1();
ThreadExam03_2 t2 = new ThreadExam03_2();
t1.start();
t2.start();
try {
t1.sleep(2000);
} catch (Exception e) {
}
System.out.println("<<main Thread 종료>>");
}
}
실행결과
class ThreadExam06_1 implements Runnable {
volatile boolean suspended = false;
volatile boolean stopped = false;
@Override
public void run() {
while(!stopped) {
if(!suspended) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (Exception e) {
}
}
}
}
public void suspend() {
suspended = true;
}
public void stop() {
stopped = true;
}
public void resume() {
suspended = false;
}
}
public class ThreadExam06 {
public static void main(String[] args) {
ThreadExam06_1 r1 = new ThreadExam06_1();
ThreadExam06_1 r2 = new ThreadExam06_1();
ThreadExam06_1 r3 = new ThreadExam06_1();
Thread t1 = new Thread(r1, "*"); // 두 번째 인자 : Thread의 이름
Thread t2 = new Thread(r2, "**");
Thread t3 = new Thread(r3, "***");
t1.start();
t2.start();
t3.start();
try {
Thread.sleep(3000); // main Thread 2초 sleep
System.out.println("t1 일시중지");
r1.suspend(); // t1 일시중지
Thread.sleep(3000);
System.out.println("t2 일시중지");
r2.suspend(); // t2 일시중지
Thread.sleep(3000);
System.out.println("t1 다시 동작");
r1.resume(); // t1을 다시 동작
Thread.sleep(3000);
System.out.println("t1 강제종료");
r1.stop();
System.out.println("t2 강제종료");
r2.stop();
Thread.sleep(3000);
System.out.println("t3 강제종료");
r3.stop();
} catch (Exception e) {
}
}
}
@Override
public void run() {
while(!stopped) { // busy waiting : 멈춰있는 것처럼 보이나 실제로는 계속해서 반복문을 실행하고 있음
if(!suspended) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (Exception e) {
}
} else {
Thread.yield(); // 따라서 CPU를 사용하지 않기 위해 다른 Thread에게 양보함
}
}
}