Thread 1 Timer Thread class Timer Thread extends

  • Slides: 50
Download presentation

* Thread를 상속받아 1초 단위로 초 시간을 출력하는 Timer. Thread 스레드 작성 class Timer.

* Thread를 상속받아 1초 단위로 초 시간을 출력하는 Timer. Thread 스레드 작성 class Timer. Thread extends Thread { int n = 0; public void run() { while(true) { // 무한루프를 실행한다. System. out. println(n); n++; try { 스레드 클래스 정의 스레드 코드 작성 1초에 한 번씩 n을 증가시켜 콘솔에 출력한다. sleep(1000); //1초 동안 잠을 잔 후 깨어난다. } } catch(Interrupted. Exception e){return; } public class Test. Thread { public static void main(String [] args) { Timer. Thread th = new Timer. Thread(); th. start(); } } 스레드 객체 생성 스레드 시작 main() 스레드 th JVM main 스레드의 스 레드 정보 Timer. Thread 스레드 run() {. . . } Timer. Thread 의 스레드 정보 0 1 2 3 4

예제 13 -1 : Thread를 상속받아 1초 단위의 타이머 만들기 import java. awt. *;

예제 13 -1 : Thread를 상속받아 1초 단위의 타이머 만들기 import java. awt. *; import javax. swing. *; class Timer. Thread extends Thread { JLabel timer. Label; public Timer. Thread(JLabel timer. Label) { this. timer. Label = timer. Label; } public void run() { int n=0; } } while(true) { timer. Label. set. Text(Integer. to. String(n)); n++; try { Thread. sleep(1000); } catch(Interrupted. Exception e) { return; } } public class Thread. Timer. Ex extends JFrame { public Thread. Timer. Ex() { set. Title(“Thread. Timer. Ex 예제”); set. Default. Close. Operation(JFrame. EXIT_ON_CLOSE); Container c = get. Content. Pane(); c. set. Layout(new Flow. Layout()); JLabel timer. Label = new JLabel(); timer. Label. set. Font(new Font(“Gothic“, Font. ITALIC, 80)); Timer. Thread th = new Timer. Thread(timer. Label); c. add(timer. Label); set. Size(300, 150); set. Visible(true); } } th. start(); public static void main(String[] args) { new Thread. Timer. Ex(); }

*Runnable 인터페이스를 상속받아 1초 단위로 초 시간을 출력하는 스레드 작성 Runnable 을 클래스로 구현

*Runnable 인터페이스를 상속받아 1초 단위로 초 시간을 출력하는 스레드 작성 Runnable 을 클래스로 구현 스레드 코드 작성 1초에 한 번씩 n을 증가시켜 콘솔에 출력한다. class Timer. Runnable implements Runnable { int n = 0; public void run() { while(true) { // 무한루프를 실행한다. System. out. println(n); n++; try { Thread. sleep(1000); // 1초 동안 잠을 잔 후 깨어난다. } 스레드 객체 생성 스레드 시작 } } } catch(Interrupted. Exception e) { return; } public class Test. Runnable { public static void main(String [] args) { Thread th = new Thread(new Timer. Runnable()); th. start(); } } main() 스레드 th 16 JVM main 스레드의 스 레드 정보 Thread 스레드 run() {. . . } Thread 의 스레드 정보 0 1 2 3 4

예제 13 -2 : Runnable인터페이스를 구현하여 1초 단위 타이머 만들기 import java. awt. *;

예제 13 -2 : Runnable인터페이스를 구현하여 1초 단위 타이머 만들기 import java. awt. *; import javax. swing. *; class Timer. Runnable implements Runnable { JLabel timer. Label; } public Timer. Runnable(JLabel timer. Label) { this. timer. Label = timer. Label; } public void run() { int n=0; while(true) { timer. Label. set. Text(Integer. to. String(n)); n++; try { Thread. sleep(1000); } catch(Interrupted. Exception e) { return; } } } public class Runnable. Timer. Ex extends JFrame { public Runnable. Timer. Ex() { set. Title(“Runnable. Timer. Ex 예제”); set. Default. Close. Operation(JFrame. EXIT_ON_CLOSE); Container c = get. Content. Pane(); c. set. Layout(new Flow. Layout()); JLabel timer. Label = new JLabel(); timer. Label. set. Font(new Font(“Gothic“, Font. ITALIC, 80)); } } Timer. Runnable runnable = new imer. Runnable(timer. Label); Thread th = new Thread(runnable); c. add(timer. Label); set. Size(300, 150); set. Visible(true); th. start(); public static void main(String[] args) { new Runnable. Timer. Ex(); }

예제 13 -3 : 깜박이는 문자열을가진 레 이블 컴포넌트 만들기 import java. awt. *;

예제 13 -3 : 깜박이는 문자열을가진 레 이블 컴포넌트 만들기 import java. awt. *; import javax. swing. *; class Flickering. Label extends JLabel implements Runnable{ public Flickering. Label(String text) { super(text); // JLabel 생성자 호출 set. Opaque(true); // 배경색 변경이 가능하도록 설정 } } public class Flickering. Label. Ex extends JFrame { public Flickering. Label. Ex() { set. Title(“Flickering. Label. Ex 예제”); set. Default. Close. Operation(JFrame. EXIT_ON_CLOSE); Container c = get. Content. Pane(); c. set. Layout(new Flow. Layout()); // 깜박이는 레이블 생성 Flickering. Label f. Label = new Flickering. Label(“깜박”); Thread th = new Thread(this); th. start(); public void run() { int n=0; while(true) { if(n == 0) set. Background(Color. YELLOW); else set. Background(Color. GREEN); if(n == 0) n = 1; else n = 0; try { Thread. sleep(500); // 0. 5초 동안 잠을 잔다. } catch(Interrupted. Exception e) { return; } } } // 깜박이지 않는 레이블 생성 JLabel label = new JLabel(“안깜박“); // 깜박이는 레이블 생성 Flickering. Label f. Label 2 = new Flickering. Label(“여기도 깜박 ”); c. add(f. Label); c. add(label); c. add(f. Label 2); } } set. Size(300, 150); set. Visible(true); public static void main(String[] args) { new Flickering. Label. Ex(); }

스레드 상태와 생명 주기 thread. A = new Thread() 스레드 상태 6 가지 •

스레드 상태와 생명 주기 thread. A = new Thread() 스레드 상태 6 가지 • NEW • RUNNABLE • WAITING • TIMED_WAITING • BLOCK • TERMINATED NEW(탄생) start() 타임아웃 I/O작업 완료 RUNNABLE (준비) yield() run() 또는 JVM에 의해 스케쥴링될 때 RUNNABLE (running, 실행중) Object. wait() WAITING(대기 ) I/O작업 요청 스레드 종료 BLOCK(봉쇄) sleep() thread. B TIMED_WAITING (시간 대기) TERMINATED (종료) Object. notify(); Object. notify. All(); ** wait(), notify. All()은 Thread의 메소드가 아니며 Object의 메소드임

main()은 자바의 main 스레드 • main() 메소드 – JVM에 의해 자동으로 스레드화 – 자바

main()은 자바의 main 스레드 • main() 메소드 – JVM에 의해 자동으로 스레드화 – 자바 스레드 : main 스레드 – main() 함수가 스레드 코드로 사용 public class Thread. Main. Ex { public static void main(String [] args) { long id = Thread. current. Thread(). get. Id(); String name = Thread. current. Thread(). get. Name(); int priority = Thread. current. Thread(). get. Priority(); Thread. State s = Thread. current. Thread(). get. State(); } } 현재 현재 System. out. println("현재 스레드 스레드 이름 = main ID = 1 우선순위 값 = 5 상태 = RUNNABLE 이름 = " + name); ID = " + id); 우선순위 값 = " + priority); 상태 = " + s);

스레드 종료와 타 스레드 강제 종료 • 스스로 종료 • 타 스레드에서 강제 종료

스레드 종료와 타 스레드 강제 종료 • 스스로 종료 • 타 스레드에서 강제 종료 : interrupt() 메소드 사용 – run() 메소드 리턴 class Timer. Thread extends Thread { int n = 0; public void run() { while(true) { System. out. println(n); // 화면에 카운트 값 출력 n++; try { sleep(1000); public static void main(String [] args) { Timer. Thread th = new Timer. Thread(); th. start(); } th. interrupt(); // Timer. Thread 강제 종료 } } } main() 스레드 만일 return 하지 않으면 스레드는 종료하지 않음 Timer. Thread 스레드 th th. interrupt(); } catch(Interrupted. Exception e){ return; // 예외를 받고 스스로 리턴하여 종료 } Interrupted. Exception 발생 catch(Interrupted. Exception e) {return; } main 스레드의 interrupt() 메소드 호출에 의해 catch 26 문 실행. 그리고 종료

예제 13 -4 : 타이머 스레드 강제 종료 public class Thread. Interrupt. Ex extends

예제 13 -4 : 타이머 스레드 강제 종료 public class Thread. Interrupt. Ex extends JFrame { Thread th; public Thread. Interrupt. Ex() { set. Title(“Thread. Interrupt. Ex 예제“); set. Default. Close. Operation(JFrame. EXIT_ON_CLOSE); Container c = get. Content. Pane(); c. set. Layout(new Flow. Layout()); import java. awt. *; import java. awt. event. *; import javax. swing. *; class Timer. Runnable implements Runnable { JLabel timer. Label; JLabel timer. Label = new JLabel(); timer. Label. set. Font(new Font(“Gothic“, Font. ITALIC, 80)); public Timer. Runnable(JLabel timer. Label) { this. timer. Label = timer. Label; } } Timer. Runnable runnable = new Timer. Runnable(timer. Label); th = new Thread(runnable); // 스레드 생성 c. add(timer. Label); public void run() { int n=0; while(true) { timer. Label. set. Text(Integer. to. String(n)); n++; try { Thread. sleep(1000); // 1초 동안 잠을 잔다. } catch(Interrupted. Exception e) { return; // 예외가 발생하면 스레드 종료 } } } // 버튼을 생성하고 Action 리스너 등록 JButton btn =new JButton(“kill Timer“); btn. add. Action. Listener(new Action. Listener() { public void action. Performed(Action. Event e) { th. interrupt(); // 타이머 스레드 강제 종료 JButton btn = (JButton)e. get. Source(); btn. set. Enabled(false); // 버튼 비활성화 } }); c. add(btn); set. Size(300, 150); set. Visible(true); th. start(); // 스레드 동작시킴 } } public static void main(String[] args) { new Thread. Interrupt. Ex(); }

flag를 이용한 종료 • 스레드 A가 스레드 B의 flag 를 true로 만들면, 스레드 B

flag를 이용한 종료 • 스레드 A가 스레드 B의 flag 를 true로 만들면, 스레드 B 가 스스로 종료하는 방식 public static void main(String [] args) { Timer. Thread th = new Timer. Thread(); th. start(); } th. finish(); // Timer. Thread 강제 종료 class Timer. Thread extends Thread { int n = 0; bool flag = false; // false로 초기화 public void finish() { flag = true; } public void run() { while(true) { System. out. println(n); // 화면에 카운트 값 출력 n++; try { sleep(1000); if(flag == true) return; // 스레드 종료 } catch(Interrupted. Exception e){ return; } } Timer. Thread 스레드 main() 스레드 flag th th. finish(); flag 멤버를 true로 변경 true false if(flag == true) return; // 스레드 종료

예제 13 -5 flag를 이용한 스레드 강제 종료 import java. awt. *; import java.

예제 13 -5 flag를 이용한 스레드 강제 종료 import java. awt. *; import java. awt. event. *; import javax. swing. *; public class Thread. Finish. Flag. Ex extends JFrame { Random. Thread th; // 스레드 레퍼런스 public Thread. Finish. Flag. Ex() { set. Title("Thread. Finish. Flag. Ex 예제"); set. Default. Close. Operation(JFrame. EXIT_ON_CLOSE); Container c = get. Content. Pane(); c. set. Layout(null); class Random. Thread extends Thread { Container content. Pane; boolean flag=false; // 스레드의 종료 명령을 표시하는 플래그. // true : 종료 지시 public Random. Thread(Container content. Pane) { this. content. Pane = content. Pane; } c. add. Mouse. Listener(new Mouse. Adapter() { public void mouse. Pressed(Mouse. Event e) { th. finish(); // Random. Thread 스레드 종료 명령 } }); set. Size(300, 200); set. Visible(true); void finish() { // 스레드 종료 명령을 flag에 표시 flag = true; } } public void run() { while(true) { int x = ((int)(Math. random()*content. Pane. get. Width())); int y = ((int)(Math. random()*content. Pane. get. Height())); JLabel label = new JLabel("Java"); //새 레이블 생성 label. set. Size(80, 30); label. set. Location(x, y); content. Pane. add(label); content. Pane. repaint(); try { Thread. sleep(300); // 0. 3초 동안 잠을 잔다. if(flag==true) { content. Pane. remove. All(); label = new JLabel("finish"); label. set. Size(80, 30); label. set. Location(100, 100); label. set. Foreground(Color. RED); content. Pane. add(label); content. Pane. repaint(); return; // 스레드 종료 } } catch(Interrupted. Exception e) { return; } } } th = new Random. Thread(c); // 스레드 생성 th. start(); // 스레드 동작시킴 public static void main(String[] args) { new Thread. Finish. Flag. Ex(); }

집계판 예제 public class Synchronized. Ex { public static void main(String [] args) {

집계판 예제 public class Synchronized. Ex { public static void main(String [] args) { Sync. Object obj = new Sync. Object(); Thread th 1 = new Worker. Thread("kitae", obj); Thread th 2 = new Worker. Thread("hyosoo", obj); th 1. start(); th 2. start(); } } class Sync. Object { int sum = 0; void add() { int n = sum; n += 10; sum = n; System. out. println(Thread. currnt. Thread(). get. Name() + " : " + sum); } int get. Sum() {return sum; } } class Worker. Thread extends Thread { Sync. Object s. Obj; Worker. Thread(String name, Sync. Object s. Obj) { super(name); this. s. Obj = s. Obj; } public void run() { int i=0; while(i<10) { s. Obj. add(); i++; } } } kitae : 10 hyosoo : 20 kitae : 30 hyosoo : 30 kitae : 40 hyosoo : 50 kitae : 60 hyosoo : 60 kitae : 70 hyosoo : 70 kitae : 80 hyosoo : 90 kitae : 100 hyosoo : 100 kitae : 110 hyosoo : 120 kitae : 130 hyosoo : 140 hyosoo : 150 add() 충돌 add() 충돌 kitae와 hyosoo가 각각 10번씩 add()를 호출하였 지만 동기화가 이루어지지 않아 공유 변수 sum에 대한 접근에 충돌이 있었고, 수를 많이 잃어버리 게 되어 누적 점수가 150 밖에 되지 못함

synchronized 사용 예 : 집계판 사례를 코딩 public class Synchronized. Ex { public static

synchronized 사용 예 : 집계판 사례를 코딩 public class Synchronized. Ex { public static void main(String [] args) { Sync. Object obj = new Sync. Object(); Thread th 1 = new Worker. Thread("kitae", obj); Thread th 2 = new Worker. Thread("hyosoo", obj); th 1. start(); th 2. start(); } } class Sync. Object { int sum = 0; synchronized void add() { int n = sum; n += 10; sum = n; System. out. println(Thread. currnt. Thread(). get. Name() + " : " + sum); } int get. Sum() {return sum; } } class Worker. Thread extends Thread { Sync. Object s. Obj; Worker. Thread(String name, Sync. Object s. Obj) { super(name); this. s. Obj = s. Obj; } public void run() { int i=0; while(i<10) { s. Obj. add(); i++; } } } • 집계판 : class Sync. Object • 각 학생 : class Worker. Thread kitae : 10 kitae : 20 kitae : 30 hyosoo : 40 hyosoo : 50 hyosoo : 60 hyosoo : 70 hyosoo : 80 hyosoo : 90 hyosoo : 100 hyosoo : 110 hyosoo : 120 hyosoo : 130 kitae : 140 kitae : 150 kitae : 160 kitae : 170 kitae : 180 kitae : 190 kitae : 200 kitae와 hyosoo가 각각 10번씩 add()를 호출하였으며 동기화가 잘 이루어져서 최종 누적 점수 sum이 200이 됨

Sync. Object 객체에 대한 스레드의 동시 접근 s. Obj = new Sync. Object(); add()

Sync. Object 객체에 대한 스레드의 동시 접근 s. Obj = new Sync. Object(); add() 대기 중 synchronized void add() { int n = sum; n += 10; sum = n; System. out. println(Thread. currnt. Thread(). } Worker. Thread get. Name() + " : " + sum); add() 실행 중 Worker. Thread Sync. Object s. Obj; public void run() { int i=0; while(i<10) { s. Obj. add(); i++; } } th 1 스레드 th 2 스레드

Buffer 클래스 • 생산자와 소비자가 공유 public class Buffer { private int data; public

Buffer 클래스 • 생산자와 소비자가 공유 public class Buffer { private int data; public synchronized int remove() { System. out. println("제품 "+data+" 소비"); return data; } public synchronized void put(int d) { System. out. println("제품 "+data+" 생산"); data = d; } }

생산자 클래스 public class Producer extends Thread { private Buffer buffer; public Producer(Buffer b)

생산자 클래스 public class Producer extends Thread { private Buffer buffer; public Producer(Buffer b) { buffer = b; } public void run() { for (int i=0; i<10; i++) { buffer. put(i); try { sleep((int) (Math. random()*1000)); } catch (Exception e) {} }

소비자 클래스 public class Consumer extends Thread{ private Buffer buffer; public Consumer(Buffer b) {

소비자 클래스 public class Consumer extends Thread{ private Buffer buffer; public Consumer(Buffer b) { buffer = b; } public void run() { for (int i=0; i<10; i++) { int d = buffer. remove(); try { sleep((int) (Math. random()*1000)); } catch (Exception e) {} }

테스트 클래스 public class Producer. Consumer. Test { public static void main(String[] args) {

테스트 클래스 public class Producer. Consumer. Test { public static void main(String[] args) { Buffer b = new Buffer(); Producer t 1 = new Producer(b); Consumer t 2 = new Consumer(b); t 1. start(); t 2. start(); } } 실행결과: 제품 제품 제품 … 0 0 0 1 1 2 3 3 3 생산 소비 생산 생산 소비 소비 생산 생산 후 소비 패턴이 형성되지 않음

wait()와 notify()

wait()와 notify()

생산자/소비자 문제 해결 public class Buffer { private int data; private boolean empty =

생산자/소비자 문제 해결 public class Buffer { private int data; private boolean empty = true; public synchronized int remove() { while (empty) { try { wait(); } catch (Interrupted. Exception e) {} } empty = true; System. out. println("제품 "+data+" 소비"); notify. All(); return data; }

생산자/소비자 문제 해결 public synchronized void put(int d) { while (!empty) { try {

생산자/소비자 문제 해결 public synchronized void put(int d) { while (!empty) { try { wait(); } catch(Interrupted. Exception e) {} } empty = false; this. data = d; System. out. println("제품 "+data+" 생산"); notify. All(); } } 실행결과: 제품 제품 제품 … 0 0 1 1 2 2 3 3 4 4 5 5 생산 소비 생산 소비

예제 : wait(), notify()를 이용한 바 채우기 import javax. swing. *; import java. awt.

예제 : wait(), notify()를 이용한 바 채우기 import javax. swing. *; import java. awt. event. *; class My. Label extends JLabel { int bar. Size = 0; // 바의 크기 int max. Bar. Size; My. Label(int max. Bar. Size) { this. max. Bar. Size = max. Bar. Size; } public void paint. Component(Graphics g) { super. paint. Component(g); g. set. Color(Color. MAGENTA); int width = (int)((double)(this. get. Width())) /max. Bar. Size*bar. Size; if(width==0) return; g. fill. Rect(0, 0, width, this. get. Height()); } synchronized void fill() { if(bar. Size == max. Bar. Size) { try { wait(); } catch (Interrupted. Exception e) { return; } } bar. Size++; repaint(); // 바 다시 그리기 notify(); } } synchronized void consume() { if(bar. Size == 0) { try { wait(); } catch (Interrupted. Exception e) { return; } } bar. Size--; repaint(); // 바 다시 그리기 notify(); } public class Tab. And. Thread. Ex extends JFrame { My. Label bar = new My. Label(100); Tab. And. Thread. Ex(String title) { super(title); this. set. Default. Close. Operation (JFrame. EXIT_ON_CLOSE); Container c = get. Content. Pane(); c. set. Layout(null); bar. set. Background(Color. ORANGE); bar. set. Opaque(true); bar. set. Location(20, 50); bar. set. Size(300, 20); c. add(bar); c. add. Key. Listener(new Key. Adapter() { public void key. Pressed(Key. Event e) { bar. fill(); } }); set. Size(350, 200); set. Visible(true); class Consumer. Thread extends Thread { My. Label bar; } Consumer. Thread(My. Label bar) { this. bar = bar; } public void run() { while(true) { try { sleep(200); bar. consume(); } catch (Interrupted. Exception e) { return; } } } c. request. Focus(); Consumer. Thread th = new Consumer. Thread(bar); th. start(); // 스레드 시작 public static void main(String[] args) { new Tab. And. Thread. Ex( "아무키나 빨리 눌러 바 채우기"); }