최용술 2002.1.22 wazupz@orgio.net http://www.jabook.org 8장 Thread 최용술 2002.1.22 wazupz@orgio.net http://www.jabook.org
목차 1. 배경 2. Thread 3. Thread 생성 4. Runnable 5. NotRunnable 6. Dead 1.1 프로세스와 스레드 2. Thread 2.1 자바의 Thread란? 2.2 Thread의 상태 2.3 Thread의 상태 그림 3. Thread 생성 3.1 Thread 상속 3.2 Runnable 구현 4. Runnable 4.1 Runnable 상태 만들기 5. NotRunnable 5.1 대기와 복구 시키기 6. Dead 6.1 스레드 죽이기 7. 멀티 스레드 7.1 멀티 스레드란? 7.2 필요성 7.3 문제점 7.4 문제 해결책-1 7.5 문제 해결책-2 8. 멀티 스레드의 생성 8.1 멀티 스레드 만들기 9. 멀티 스레드의 제어 9.1 Priority 예제 9.2 Synchronization 예제 10. 마무리 10.1 마무리 2018-12-05
1. 배경 1.1 프로세스와 스레드 최용술 2002.1.21 wazupz@orgio.net http://www.jabook.org
1.1 프로세스와 스레드 Process Thread 실행 중인 프로그램 ex) word 프로세스 내부에서 실행되는 일련의 작업 1. 배경 1.1 프로세스와 스레드 Process 실행 중인 프로그램 ex) word Thread 프로세스 내부에서 실행되는 일련의 작업 ex) save or print 2018-12-05
2.1 자바의 Thread란? 2.2 Thread의 상태 2.3 Thread의 상태 그림 최용술 2002.1.21 wazupz@orgio.net http://www.jabook.org
2.1 자바의 Thread란? 생성만 시켜주면 알아서 실행 후에 자동으로 종료 두 가지 방법으로 생성 Thread클래스를 상속 Runnable인터페이스를 구현 class NewThread extends Thread{ ……… } class SoloRunnable implements Runnable{ ………. } 2018-12-05
2.2 Thread의 상태 Thread 생성 Runnable Not Runnable Dead 스레드의 시작 스레드가 활동 가능한 상태 실행 Queue : 실제로 CPU를 점유한 하나의 스레드만이 존재 실행 대기 Queue : CPU를 점유하기 위해 실행 대기 중인 Runnable상태의 여러 스레드가 존재 Not Runnable 스레드의 활동이 불가능한 상태 Dead 스레드의 종료 2018-12-05
2.3 Thread의 상태 그림 스레드의 상태 분류 Thread생성, Runnable, NotRunnable, Dead 자바 런타임 스케줄러 yield() start() wait() sleep() notify() notifyAll() Time-out run()의 종료 return break stop() 실행 Queue 실행 대기 Queue 2018-12-05 그림 2.3-1 스레드의 상태
3. Thread 생성 3.1 Thread 상속 3.2 Runnable 구현 최용술 2002.1.21 wazupz@orgio.net http://www.jabook.org
3.1 Thread 상속 스레드 생성 start() run() run()은 반드시 재정의해야 함 3. 스레드의 생성 3.1 Thread 상속 스레드 생성 start() run() run()은 반드시 재정의해야 함 Thread클래스의 멤버 사용 가능 사용자 정의 예외 발생하기 import java.lang.Thread; class NewThread extends Thread { //To do something… public void run() { //Thread Body 재정의 } //To do Something public class NewThreadMain { public static void main(String[] args){ NewThread n = new NewThread(); //스레드의 생성 n.start(); //스레드의 시작 System.out.println(n.getName()); n.setName("스레드래!"); try{ Thread.sleep(2000); System.out.println(n.toString()); }catch(InterruptedException e){ C:\javaExample\08>javac NewThreadMain.java C:\javaExample\08>java NewThreadMain //기본적인 스레드의 이름 (Thread-n : n은 정수로 증가) Thread-1 //setName()으로 스레드의 이름을 변경 스레드래! //sleep(2000) 때문에 2초 후에 다음의 문장 출력 //toString()은 Thread[스레드 이름, 우선권, 스레드 그룹] Thread[스레드래!,5,] 2018-12-05
3.2 Runnable 구현 Runnable인터페이스 구현 run()을 반드시 재정의 3. 스레드의 생성 3.2 Runnable 구현 Runnable인터페이스 구현 run()을 반드시 재정의 Thread클래스의 멤버들을 사용하지 못함 단, sleep()은 static이기 때문에 사용 가능 사용자 정의 예외 발생하기 class SoloRunnable implements Runnable{ private int number = 0; public SoloRunnable(int n) { System.out.println(":스레드시작"); number = n; } public void run() { int i = 0; while(i < number) { System.out.print(i + "\t"); i++; System.out.println(":스레드종료"); public class SoloRunnableMain { public static void main(String args[] ) { new Thread(new SoloRunnable(10)).start(); C:\javaExample\08>javac SoloRunnableMain.java C:\javaExample\08>java SoloRunnableMain :스레드시작 0 1 2 3 4 5 6 7 8 9 :스레드종료 2018-12-05
4. Runnable 4.1 Runnable 상태 만들기 최용술 2002.1.21 wazupz@orgio.net http://www.jabook.org
4.1 Runnable 상태 만들기 Runnable인터페이스를 구현 run()메서드를 반드시 재정의해야 함 run()메서드를 재정의한 클래스를 Thread클래스의 매개변수로 삽입 사용자 정의 예외 발생하기 import java.awt.*; class SoloFrame extends Frame implements Runnable { private int number = 0; public SoloFrame(int n) { number = n; Thread t = new Thread(this); t.start(); System.out.println(t.getName() + ":스레드시작"); } public void run() { int i = 0; while(i < number) { System.out.print(i + "\t"); i++; System.out.println(":스레드종료"); public class SoloFrameMain { public static void main(String[] args) { //스레드의 객체 생성 SoloFrame s = new SoloFrame(10); s.setSize(100, 100); s.show(); C:\javaExample\Thread>javac SoloFrameMain.java C:\javaExample\Thread>java SoloFrameMain Thread-2:스레드시작 0 1 2 3 4 5 6 7 8 9 :스레드종료 2018-12-05
5. NotRunnable 5.1 대기와 복구 시키기 최용술 2002.1.21 wazupz@orgio.net http://www.jabook.org
5.1 대기와 복구 시키기 sleep(long millis) 사용 Object클래스의 wait()와 notify() 사용 5. NotRunnable 5.1 대기와 복구 시키기 sleep(long millis) 사용 원하는 대기 시간을 1/1000초 단위로 삽입 설정 시간 경과 후 자동 복귀 Object클래스의 wait()와 notify() 사용 wait()로 대기시키고, notify()로 복귀 시킴 NotRunnableThread.java (사용자 정의 예외 발생하기) import java.util.*; class NotRunnableThread extends Thread {//스레드상속 private int number = 0; public NotRunnableThread(int n) { System.out.println(this.getName()+":스레드시작"); number = n; } public void run() { int i = 0; while(i < number) { System.out.println(this.getName() +":"+i + new Date().toString() + "\t"); try{ this.sleep(2000); }catch(Exception e){System.out.println(e);} i++; System.out.println(":스레드종료"); public class NotRunnableThreadMain { public static void main(String args[] ) { NotRunnableThread s = new NotRunnableThread(5); s.start(); C:\javaExample\08>javac NotRunnableThreadMain.java C:\javaExample\08>java NotRunnableThreadMain Thread-1:스레드시작 Thread-1:0Wed Jan 23 10:12:52 KST 2002 Thread-1:1Wed Jan 23 10:12:54 KST 2002 Thread-1:2Wed Jan 23 10:12:56 KST 2002 Thread-1:3Wed Jan 23 10:12:58 KST 2002 Thread-1:4Wed Jan 23 10:13:00 KST 2002 :스레드종료 2018-12-05
6. Dead 6.1 스레드 죽이기 최용술 2002.1.21 wazupz@orgio.net http://www.jabook.org
6.1 스레드 죽이기 run()의 종료 stop()은 시스템 안전상 deprecated 됨 break와 return을 사용 6. Dead 6.1 스레드 죽이기 run()의 종료 stop()은 시스템 안전상 deprecated 됨 break와 return을 사용 TerminateThread.java (스레드의 생성과 종료 예제) class MyThread extends Thread { private int limit = 0; private boolean flag = false; public MyThread(int limit) { this.limit = limit; } public void run() { int count = 0; while(!flag) { try { this.sleep(100); } catch(InterruptedException e) {} if(count == limit) flag = true; System.out.println(this.getName() + " : " + count); count++; System.out.println(this.getName() + "종료"); public class TerminateThread { public static void main(String args[]) { System.out.println("작업시작"); MyThread r1 = new MyThread(3); MyThread r2 = new MyThread(7); MyThread r3 = new MyThread(5); r1.start(); r2.start(); r3.start(); C:\javaExample\08>javac TerminateThread.java C:\javaExample\08>java TerminateThread 작업시작 Thread-1 : 0 Thread-2 : 0 Thread-3 : 0 Thread-1 : 1 Thread-2 : 1 Thread-3 : 1 Thread-1 : 2 Thread-2 : 2 Thread-3 : 2 Thread-1 : 3 Thread-1종료 Thread-2 : 3 Thread-3 : 3 Thread-2 : 4 Thread-3 : 4 Thread-2 : 5 Thread-3 : 5 Thread-3종료 Thread-2 : 6 Thread-2 : 7 Thread-2종료 2018-12-05
7.1 멀티 스레드란? 7.2 필요성 7.3 문제점 7.4 문제 해결책-1 7.5 문제 해결책-2 7. 멀티 스레드 7.1 멀티 스레드란? 7.2 필요성 7.3 문제점 7.4 문제 해결책-1 7.5 문제 해결책-2 최용술 2002.1.21 wazupz@orgio.net http://www.jabook.org
7.1 멀티 스레드란? Multi-processing Multi-tasking Multi-threading 7. 멀티 스레드 7.1 멀티 스레드란? Multi-processing 여러 개의 CPU에서 동시에 여러 개의 프로세스가 수행 Ex) Dual CPU Multi-tasking 하나의 CPU에서 동시에 둘 이상의 작업을 수행 Ex) 한글을 사용하면서 동시에 웹 브라우저를 실행시킴 Multi-threading 하나의 프로세스내에서 여러 개의 스레드가 작업을 수행 Ex) 스타크를 하면서 정찰과 자원획득, 건물 건축을 동시에 수행 모든 활동들이 하나의 스레드로 작동함 2018-12-05
7.2 필요성 동시에 두 가지 이상의 작업을 수행하기 위하여 Ex) 동시에 for문을 2개 이상 실행해야 할 때 7. 멀티 스레드 7.2 필요성 동시에 두 가지 이상의 작업을 수행하기 위하여 Ex) 동시에 for문을 2개 이상 실행해야 할 때 for() { …… } 스레드 1 스레드 2 스레드 3 실행 대기 Queue 실행스레드 실행 Queue 그림 7.2-1 멀티 스레드의 필요성 2018-12-05
7.3 문제점 여러 개의 스레드가 하나의 자원을 동시에 사용할 때 발생 7. 멀티 스레드 자료를 동시에 요청할 때 bottleneck현상 발생 동시사용과 병목현상으로 deadlock발생 데이터의 무결성에 대한 문제 발생 run() { 공유 데이터 요청 } B 스레드 자원 공유 데이타 C 스레드 D 스레드 A 스레드 자원 점유 자원 요청 Deadlock 발생 A 스레드 자료점유 여러 개의 동시 자료요청 2018-12-05 그림 7.3-1 멀티 스레드의 문제점
7.4 문제 해결책-1 제어적인 측면 7. 멀티 스레드 우선권(priority) 부여 수동적인 대책 컴파일러에게 위임 스레드의 기본 우선권은 5로 부여됨 프로그래머가 임의로 부여 가능 setPriority(int newPriority)로 설정 우선권 설정 예 SoloThread s = new SoloThread(5); s.setPriority(int newPriority); setPriority(int newPriority) : 새로운 우선권을 설정 (1-10) getPriority() : 현재 설정된 우선권을 알아냄 public static final int MIN_PRIORITY : 1 public static final int NORM_PRIORITY : 5 public static final int MAX_PRIORITY : 10 자원 공유 데이터 run() { 요청 } A 스레드 자원 점유 우선권 부여 A 스레드 자료점유 여러 개의 동시 자료요청 2018-12-05 그림 7.4-1 스레드의 priority
7.5 문제 해결책-2 7. 멀티 스레드 자료적인 측면 Runnable 상태 sleep(), wait() 시스템에 미루기 동기화(synchronized) 프로그래머가 직접 제어 보다 효율적 제어를 위해 wait()와 notify()를 사용 메서드 전체를 동기화한 예제 public synchronized void method(){ …… } 메서드 부분을 동기화한 예제 public void method(){ synchronized(this){ …… } NotRunnable 상태 run() { 공유 데이터 요청 } A 스레드 자원 점유 Runnable 상태 Synchronized로 lock을 건 상태 locked sleep(), wait() Timeout notify() 사용 중이면 기다려야지 !! 자원 2018-12-05 그림 7.4-1 스레드의 동기화
8. 멀티 스레드의 생성 8.1 멀티 스레드 만들기 최용술 2002.1.21 wazupz@orgio.net http://www.jabook.org
8.1 멀티 스레드 만들기 main()안에 여러 개의 스레드 생성 8. 멀티 스레드의 생성 멀티 스레드의 생성 public static void main(String[] args){ Thread thread1 = new Thread(); Thread thread2 = new Thread(); Thread thread3 = new Thread(); thread1.start(); thread2.start(); thread3.start(); } 2018-12-05
9.1 Priority 예제 9.2 Synchronization 예제 9. 멀티 스레드의 제어 9.1 Priority 예제 9.2 Synchronization 예제 최용술 2002.1.21 wazupz@orgio.net http://www.jabook.org
9.1 Priority 예제 스레드의 기본 우선권은 5로 부여됨 프로그래머가 임의로 부여 가능 9. 멀티 스레드의 제어 9.1 Priority 예제 스레드의 기본 우선권은 5로 부여됨 프로그래머가 임의로 부여 가능 setPriority(int newPriority)로 설정 C:\javaExample\Thread>javac PriorityThreadMain.java C:\javaExample\Thread>java PriorityThreadMain Main메서드시작 Thread.MAX_PRIORITY:10 Thread-1:스레드시작 Thread-2:스레드시작 ……… Main메서드종료 Thread-5:p:5:0 Thread-3:p:3:0 Thread-4:p:4:0 ……… 0:p:10:4 Thread-9:p:9:4 Thread-5:p:5:4 Thread-6:p:6:스레드종료 ……… PriorityThreadMain.java (우선권 설정 예제) class SoloThread extends Thread {//스레드상속 private int number = 0; public SoloThread(int n){ System.out.print(this.getName() + ":스레드시작\t"); number = n; } public void run(){ int i = 0; while(i < number){ System.out.print(getName() + ":p:"+this.getPriority() + ":"+i + "\t"); try{ this.sleep(1000); }catch(Exception e){System.out.println(e);} i++; System.out.println("\n" + this.getName() + ":p:“ + this.getPriority() + ":스레드종료\t"); public class PriorityThreadMain{ public static void main(String[] args){ System.out.println("Main메서드시작"); System.out.println("Thread.MAX_PRIORITY:" +Thread.MAX_PRIORITY); System.out.println("Thread.MIN_PRIORITY:" +Thread.MIN_PRIORITY); System.out.println("Thread.NORM_PRIORITY:" +Thread.NORM_PRIORITY); for(int i=Thread.MIN_PRIORITY; i<Thread.MAX_PRIORITY + 1; i++){ SoloThread s = new SoloThread(5); s.setPriority(i); s.start(); System.out.println("Main메서드종료"); 2018-12-05
9.2 Synchronization 예제 시스템에 미루기 프로그래머가 직접 제어 synchronized 9. 멀티 스레드의 제어 9.2 Synchronization 예제 시스템에 미루기 synchronized 프로그래머가 직접 제어 wait()와 notify() 이용 C:\javaExample\Thread>javac SyncThreadMain C:\javaExample\Thread>java SyncThreadMain Starting SyncTest... Thread-1 Putting Char:! Thread-2 Putting Char:" ……… Thread-19 Poping:" OK Thread-20 Poping:! OK SyncThreadMain.java (동기화 예제) import java.util.*; class SyncStack { private Vector buffer = new Vector(); public synchronized char pop(){ char c; c = ((Character)(buffer.remove(buffer.size()-1))).charValue(); return c; } public void push(char c){ synchronized(this){ Character charObj = new Character(c); buffer.addElement(charObj); class PopThread extends Thread{ private SyncStack ss = null; public PopThread(SyncStack ss){ this.ss = ss; public void run(){ System.out.println(this.getName() + " Poping:" + ss.pop() + " OK"); class PutThread extends Thread{ private char c; public PutThread(SyncStack ss, char c){ this.c = c; System.out.println(this.getName() + " Putting Char:" + c); ss.push(c); public class SyncThreadMain{ public static void main(String args[]){ System.out.println("Starting SyncTest..."); SyncStack ss= new SyncStack(); for(int i=0; i<10; i++) new PutThread(ss,(char)(i+33)).start(); new PopThread(ss).start(); 2018-12-05
10. 마무리 10.1 마무리 최용술 2002.1.21 wazupz@orgio.net http://www.jabook.org
10.1 마무리 스레드란? 스레드의 상태 스레드의 구현 멀티 스레드의 우선권 멀티 스레드의 동기화 10. 마무리 10.1 마무리 스레드란? 생성만 시켜주면 자동으로 작동하다 종료하는 작업 스레드의 상태 스레드의 생성 : Thread thread = new Thread(); Runnable : thread.start() NotRunnable : sleep()과 wait()의 호출 Dead : run()메서드의 종료 스레드의 구현 Thread클래스를 상속 : extends Thread Runnable인터페이스를 구현 : implements Runnable 멀티 스레드의 우선권 임의의 우선권을 부여해 스레드들을 제어 : getPriority(), setPriority 멀티 스레드의 동기화 효율적으로 공유 자원에 대한 접근을 통제 시스템에 미루기 : synchronized 프로그래머가 직접 제어 : wait()와 notify() 2018-12-05