명품 JAVA Essential.

Slides:



Advertisements
Similar presentations
Chap02 자바환경과 자바 프로그램 Section 1 : 자바 개발 환경 Section 2 : 자바 통합 환경 Section 3 : 자바 응용 프로그램과 애플릿 프로그램 Section 4 : 자바 응용 프로그램 Section 5 : 자바 애플릿 프로그램.
Advertisements

명품 JAVA Programming 제 3 장 반복문, 배열, 예외처리.
명품 JAVA Programming 제 13 장 스레드와 멀티태스킹.
어서와 Java는 처음이지! 제3장선택과 반복.
11장. 프로토콜 핸들러 AI &HC I LAB 김 성 현.
6장 java.applet.Applet의 네트워크 메쏘드들
명품 JAVA Essential.
어서와 Java는 처음이지! 제2장 자바 프로그래밍 기초.
- 계산기 GUI 구성하기 - 조원: 박강국 오정은 이귀식 김도윤 안영진.
10. 예외 처리.
Ch.22 Command Pattern 장 덕 성 계명대학교 컴퓨터공학과 정보공학실험실
컴퓨터 응용 및 실습 Part1. OOP&Java Programming data type Review
9장. 스윙 프로그래밍.
GUI 이벤트, 이벤트 리스너와 이벤트 소스 그림 그리기 내부 클래스
객체지향 프로그래밍.
7장 배열 ③.
명품 JAVA Programming 제 13 장 스레드와 멀티태스킹.
명품 JAVA Essential.
제8장 쓰레드 프로그래밍.
명품 JAVA Programming.
어서와 Java는 처음이지! 제16장 스레드.
자바란 무엇인가? JDK의 다운로드 및 설치 방법 Hello, Java 프로그램의 작성 자바 프로그램의 작동 원리
윤 홍 란 제3장 클래스와 객체의 사용-1 윤 홍 란
9장 AWT(1).
[ 단원 08 ] 예외처리와 스레드.
메소드 호출과 힙 원격 메소드 호출 서블릿 엔터프라이즈 자바 빈즈
Power Java 제4장 자바 프로그래밍 기초.
10장 객체-지향 프로그래밍 II ©창병모.
8장 자바 입출력.
명품 JAVA Programming 제 12 장 그래픽.
Power Java 제10장 배열.
객체지향 언어와 클래스, 객체 ㅎㅎ 개요 클래스의 선언, 객체의 생성 및 속성 참조 방식 멤버 변수 메소드 한빛미디어(주)
Swing 컴포넌트 텍스트 컴포넌트 텍스트 필드 텍스트 영역 스크롤 페인 체크 박스 라디오 버튼.
01. 직렬화와 역직렬화에 대하여 객체의 직렬화 직렬화와 역직렬화
명품 JAVA Essential.
5장 조건과 반복 ③.
실전 사운드 처리 프로그래밍 Lecture #11.
명품 Java Programming.
Java의 정석 제 12 장 쓰레드(thread) Java 정석 남궁성 강의
최용술 장 Thread 최용술
Chap07 예외 처리 7.1 예외의 개요 7.2 예외 관련 클래스 7.3 예외 처리.
10장 다중 스레드 10.1 스레드 개요 10.2 Thread 클래스 10.3 스레드 생성
2장 자바환경과 자바 프로그램 2.1 자바 개발 환경 2.2 자바 통합환경 2.3 자바 응용 프로그램과 애플릿 프로그램
9장 AWT(1).
명품 JAVA Programming 제 15 장 애플릿과 멀티미디어.
Chap08 다중 스레드 8.1 스레드 개요 8.2 Thread 클래스와 스레드 생명주기 8.3 스레드 생성과 사용
객체지향적인 프로그래밍에 대한 이해 클래스와 객체의 개념에 대한 이해
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
Subject : Thread Written by: 김형근,류명운.
03. 안드로이드를 위한 Java 문법 제목. 03. 안드로이드를 위한 Java 문법 제목.
Ch.1 Iterator Pattern <<interface>> Aggregate +iterator
Chap10 다중 스레드 Section 1 : 스레드 개요 Section 2 : Thread 클래스와 스레드 생명주기
제 2장 어휘구조와 자료형 토 큰 리 터 럴 주 석 자 료 형 배 열 형.
컴퓨터공학실습(I) 3주 인공지능연구실.
Java IT응용시스템공학과 김형진 교수 5장. 객체지향 개념 public class SumTest {
JA A V W. 04.
자바 5.0 프로그래밍.
Java 3장. 자바의 기본 구조 I : 변수, 자료형, 연산자 public class SumTest {
제8장 쓰레드 프로그래밍.
제 4 장 클래스 작성 Lab 4- 2.
Outline 클래스의 해부 캡슐화(Encapsulation) 메쏘드의 해부 그래픽 객체(Graphical Objects)
JVM의 구조와 메모리 모델 JVM의 내부 구조 클래스 파일 클래스 로더 메소드(method) 영역 힙(heap) 영역
C# 10장. 참조형.
Chapter 4 클래스 작성.
자바 프로그래밍 Thread를 이용한 애니메이션 서울호서전문학교 게임프로그램개발과.
Java 5장. 객체지향 개념 public class SumTest {
제8장 쓰레드 프로그래밍.
Chapter2 : 자바환경과 자바 프로그램 2.1 자바 개발 환경 2.2 자바 통합개발환경(IDE)
Chapter8 : 인터페이스와 패키지 8.1 인터페이스 개요와 인터페이스 정의 8.2 인터페이스의 사용
임베디드 프로그래밍 Lecture #
Presentation transcript:

명품 JAVA Essential

학습 목표 멀티태스킹과 스레드의 개념 이해 Thread 클래스를 상속받아 자바 스레드 만들기 Runnable 인터페이스를 구현하여 자바 스레드 만들기 스레드 종료 시키기 스레드의 동기화 개념과 필요성 이해 synchronized로 간단한 스레드 동기화 wait()-notify()로 간단한 스레드 동기화

멀티태스킹(multi-tasking) 개념 여러 개의 작업(태스크)이 동시에 처리되는 것

멀티태스킹 프로그램 사례

스레드와 운영체제 스레드(thread) 멀티스레딩(multi-threading) 스레드 구성 운영체제에 의해 관리되는 하나의 작업 혹은 태스크 스레드와 태스크(혹은 작업)은 바꾸어 사용해도 무관 멀티스레딩(multi-threading) 여러 스레드를 동시에 실행시키는 응용프로그램을 작성하는 기법 스레드 구성 스레드 코드 작업을 실행하기 위해 작성한 프로그램 코드 개발자가 작성 스레드 정보 스레드 명, 스레드 ID, 스레드의 실행 소요 시간, 스레드의 우선 순위 등 운영체제가 스레드에 대해 관리하는 정보

멀티태스킹과 멀티스레딩 멀티태스킹 구현 기술 멀티프로세싱(multi-processing) 하나의 응용프로그램이 여러 개의 프로세스를 생성하고, 각 프로세스 가 하나의 작업을 처리하는 기법 각 프로세스 독립된 메모리 영역을 보유하고 실행 프로세스 사이의 문맥 교환에 따른 과도한 오버헤드와 시간 소모의 문제점 멀티스레딩(multi-threading) 하나의 응용프로그램이 여러 개의 스레드를 생성하고, 각 스레드가 하나의 작업을 처리하는 기법 하나의 응용프로그램에 속한 스레드는 변수 메모리, 파일 오픈 테이 블 등 자원으로 공유하므로, 문맥 교환에 따른 오버헤드가 매주 작음 현재 대부분의 운영체제가 멀티스레딩을 기본으로 하고 있음

웹 서버의 멀티스레딩 사례 웹문서 요청 웹 클라이언트 웹 서비스 스레드 웹문서 전송 각 클라이언트 당 웹 서비스 스레드 생성 웹 서버 시스템

자바 스레드(Thread)와 JVM 자바 스레드 JVM과 자바의 멀티스레딩 응용프로그램은 하나 이상의 스레드로 구성 가능

자바 스레드 만들기 스레드 만드는 2 가지 방법 java.lang.Thread 클래스를 상속받아 스레드 작성 java.lang.Runnable 인터페이스를 구현하여 스레드 작성

Thread 클래스를 상속받아 스레드 만들기(1) 주요 메소드

Thread 클래스를 상속받아 스레드 만들기(2) Thread를 상속받아 run() 오버라이딩 Thread 클래스 상속. 새 클래스 작성 run() 메소드 작성 run() 메소드를 스레드 코드라고 부름 run() 메소드에서 스레드 실행 시작 스레드 객체 생성 생성된 객체는 필드와 메소드를 가진 객체일 뿐 스레드로 작동하지 않음 스레드 시작 start() 메소드 호출 스레드로 작동 시작 스레드 객체의 run()이 비로소 실행 JVM에 의해 스케쥴되기 시작함 class TimerThread extends Thread { .................................................... public void run() { // run() 오버라이딩 ......................... } TimerThread th = new TimerThread(); th.start();

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

예제 12-1 : Thread를 상속받아 1초 단위 타이머 스레드 만들기 import java.awt.*; import javax.swing.*; class TimerThread extends Thread { JLabel timerLabel; // 타이머 값이 출력되는 레이블 public TimerThread(JLabel timerLabel) { this.timerLabel = timerLabel; } // 스레드 코드. run()이 종료하면 스레드 종료 public void run() { int n=0; // 타이머 카운트 값 while(true) { // 무한 루프 timerLabel.setText(Integer.toString(n)); n++; // 카운트 증가 try { Thread.sleep(1000); // 1초동안 잠을 잔다. catch(InterruptedException e) { return;} public class ThreadTimerEx extends JFrame { public ThreadTimerEx() { setTitle("Thread를 상속받은 타이머 스레드 예제"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container c = getContentPane(); c.setLayout(new FlowLayout()); // 타이머 값을 출력할 레이블 생성 JLabel timerLabel = new JLabel(); timerLabel.setFont(new Font("Gothic", Font.ITALIC, 80)); c.add(timerLabel); TimerThread th = new TimerThread(timerLabel); setSize(250,150); setVisible(true); th.start(); // 타이머 스레드의 실행을 시작하게 한다. } public static void main(String[] args) { new ThreadTimerEx();

Runnable 인터페이스로 스레드 만들기 스레드 객체 생성 스레드 시작 start() 메소드 호출 스레드로 작동 시작 스레드 객체의 run()이 비로소 실행 JVM에 의해 스케쥴되기 시작함 class TimerRunnable implements Runnable { ................................................................ public void run() { // run() 메소드 구현 ......................... } Thread th = new Thread(new TimerRunnable()); th.start();

예제 12-2 : Runnable 인터페이스를 이용하여 1초 단위로 출력하는 타이머 스레드 만들기 import java.awt.*; import javax.swing.*; class TimerRunnable implements Runnable { JLabel timerLabel; public TimerRunnable(JLabel timerLabel) { this.timerLabel = timerLabel; } // 스레드 코드. run()이 종료하면 스레드 종료 public void run() { int n=0; // 타이머 카운트 값 while(true) { // 무한 루프 timerLabel.setText(Integer.toString(n)); n++; try { Thread.sleep(1000); // 1초동안 잠을 잔다. catch(InterruptedException e) { return; } public class RunnableTimerEx extends JFrame { public RunnableTimerEx() { setTitle("Runnable을 구현한 타이머 스레드 예제"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container c = getContentPane(); c.setLayout(new FlowLayout()); // 타이머 값을 출력할 레이블 생성 JLabel timerLabel = new JLabel(); timerLabel.setFont(new Font("Gothic", Font.ITALIC, 80)); c.add(timerLabel); // 레이블을 컨텐트팬에 부착 TimerRunnable runnable = new TimerRunnable(timerLabel); Thread th = new Thread(runnable); // 스레드 객체 생성 setSize(250,150); setVisible(true); th.start(); // 타이머 스레드가 실행을 시작하게 한다. } public static void main(String[] args) { new RunnableTimerEx();

main 스레드 main 스레드 JVM이 응용프로그램을 실행할 때 디폴트로 생성되는 스레드 main() 메소드 실행 시작

예제 12-3 : main 스레드 확인과 스레드 정보를 알아내는 코드 main() 메소드 내에서 현재 스레드 정보를 가진 Thread 객체를 알아내어 현재 실행중인 스레드에 관한 다양한 정보를 출력한다. public class ThreadMainEx { public static void main(String [] args) { long id = Thread.currentThread().getId(); String name = Thread.currentThread().getName(); int priority = Thread.currentThread().getPriority(); Thread.State s = Thread.currentThread().getState(); System.out.println("현재 스레드 이름 = " + name); System.out.println("현재 스레드 ID = " + id); System.out.println("현재 스레드 우선순위 값 = " + priority); System.out.println("현재 스레드 상태 = " + s); } 현재 스레드 이름 = main 현재 스레드 ID = 1 현재 스레드 우선순위 값 = 5 현재 스레드 상태 = RUNNABLE

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

예제 12-4 : 진동하는 스레드와 스레드의 강제 종료 Runnable을 받은 스레드를 작성하여 프레임이 심하게 진동하도록 프로그램을 작성하라. 그리고 컨텐트팬에 마우스를 클릭하면 진동 스레드를 종료시켜 진동이 멈추도록 하라

예제 12-4 정답 import java.awt.*; public void run() { // 프레임의 진동을 일으키기 위해 import java.awt.event.*; import javax.swing.*; import java.util.Random; public class VibratingFrame extends JFrame implements Runnable { Thread th; // 진동하는 스레드 public VibratingFrame() { setTitle("진동하는 프레임 만들기"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(200,200); setLocation(300,300); setVisible(true); getContentPane().addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { if(!th.isAlive()) return; th.interrupt(); } }); th = new Thread(this); // 진동하는 스레드 객체 생성 th.start(); // 진동 시작 public void run() { // 프레임의 진동을 일으키기 위해 // 20ms마다 프레임의 위치를 랜덤하게 이동 Random r = new Random(); while(true) { try { Thread.sleep(20); // 20ms 잠자기 } catch(InterruptedException e){ return; // 리턴하면 스레드 종료 int x = getX() + r.nextInt()%5; // 새 위치 x int y = getY() + r.nextInt()%5; // 새 위치 y setLocation(x, y); // 프레임의 위치 이동 public static void main(String [] args) { new VibratingFrame(); Runnable 인터페이스 구현. 프레임에 run() 메소드 반드시 작성 필요 프레임 객체가 Runnable 인터페이스를 구현한 객체이므로 this 가능

스레드 동기화(Thread Synchronization) 멀티스레드 프로그램 작성시 주의점 다수의 스레드가 공유 데이터에 동시에 접근하는 경우 공유 데이터의 값에 예상치 못한 결과 발생 가능 스레드 동기화 동기화란? 스레드 사이의 실행순서 제어, 공유데이터에 대한 접근을 원활하게 하는 기법 멀티스레드의 공유 데이터의 동시 접근 문제 해결 방법1) 공유 데이터를 접근하는 모든 스레드의 한 줄 세우기 방법2) 한 스레드가 공유 데이터에 대한 작업을 끝낼 때까지 다른 스레드가 대 기 하도록 함 자바의 스레드 동기화 방법 - 2가지 synchronized 키워드로 동기화 블록 지정 wait()-notify() 메소드로 스레드의 실행 순서 제어

동기화의 필요성 - 두 스레드가 프린터에 동시 쓰기로 충돌하는 경우 스레드 B “자바는 좋은 것이야. 배워서 많이 알고 취직도 잘 되고.” 스레드 A 스레드 B 스레드 A가 프린터 사용을 끝낼때까지 기다린다. 스레드 A “자바는 좋은 것이야. 배워서 많이 알고 취직도 잘 되고.” “I love you forever.” “I love you forever.” I love you forever. I love 자바는 좋은 것이야. you 배워서 많이 forever. 알고 취직도 잘 되고. 두 스레드가 동시에 프린터에 쓰는 경우 문제 발생 한 스레드의 출력이 끝날 때까지 다른 스레드 대기함으로써 정상 출력

synchronized 블록 지정 synchronized 키워드 synchronized 블록이 실행될 때, 스레드가 독점적으로 실행해야 하는 부분(동기화 코드)을 표시하는 키워드 임계 영역(criitical section) 표기 키워드 synchronized 블록 지정 방법 메소드 전체 혹은 코드 블록 synchronized 블록이 실행될 때, 먼저 실행한 스레드가 모니터 소유 모니터란 해당 객체를 독점적으로 사용할 수 있는 권한 모니터를 소유한 스레드가 모니터를 내놓을 때까지 다른 스레드 대기 synchronized void print(String text) { // 동기화 메소드 ... for(int i=0; i<text.length(); i++) // text의 각 문자 출력 System.out.print(text.charAt(i)); } void execute(String text) { ... synchronized(this) { // 동기화 코드 블록 for(int i=0; i<text.length(); i++) System.out.print(text.charAt(i)); } synchronized 메소드 synchronized 코드 블록

예제 12-5 : 두 스레드가 공유 프린터 객체를 통해 동시에 출력하는 경우 동기화 - synchronized 블록 지정 public class SynchronizedEx { public static void main(String[] args) { SharedPrinter p = new SharedPrinter(); // 공유 데이터 생성 String [] engText = { "Wise men say, ", "only fools rush in", "But I can't help, ", "falling in love with you", "Shall I stay? ", "Would it be a sin?", "If I can't help, ", "falling in love with you" }; String [] korText = { "동해물과 백두산이 마르고 닳도록, ", "하느님이 보우하사 우리 나라 만세", "무궁화 삼천리 화려강산, ", "대한 사람 대한으로 길이 보전하세", "남산 위에 저 소나무, 철갑을 두른 듯", "바람서리 불변함은 우리 기상일세.", "대한 사람 대한으로 길이 보전하세" }; Thread th1 = new WorkerThread(p, engText);//영문출력스레드 Thread th2 = new WorkerThread(p, korText);//국문출력스레드 // 두 스레드를 실행시킨다. th1.start(); th2.start(); } // 두 WorkerThread 스레드에 의해 동시 접근되는 공유 프린터 class SharedPrinter { // synchronized를 생략하면 // 한글과 영어가 한 줄에 섞여 출력되는 경우가 발생한다. synchronized void print(String text) { // Thread.yield(); for(int i=0; i<text.length(); i++) System.out.print(text.charAt(i)); System.out.println(); } // 스레드 클래스 class WorkerThread extends Thread { SharedPrinter p; // 공유 프린터 주소 String [] text; WorkerThread(SharedPrinter p, String[] text) { this.p = p; this.text = text; // 스레드는 반복적으로 공유 프린터에 10번 접근 text[] 출력 public void run() { for (int i=0; i<text.length; i++) // 한 줄씩 출력 p.print(text[i]); // 공유 프린터에 출력

예제 12-5 실행 결과 Wise men say, only fools rush in But I can't help, 한글이 한 줄 출력되든지 영문이 한 줄 출력되는 것이 정상이지만 synchronized가 생략된 print() 메소드가 두 스레드에 의해 동시 호출되면 두 스레드의 동기화가 이루어지지 않아서 한글과 영문이 섞여 출력된다. Wise men say, only fools rush in But I can't help, falling in love with you Shall I stay? Would it be a sin? If I can't help, 동해물과 백두산이 마르고 닳도록, 하느님이 보우하사 우리 나라 만세 무궁화 삼천리 화려강산, 대한 사람 대한으로 길이 보전하세 남산 위에 저 소나무, 철갑을 두른 듯 바람서리 불변함은 우리 기상일세. Wise 동해물과 백두산이 마르고 닳도록, men say, only fools rush in But I can't help, 하느님이 보우하사 우리 나라 만세 falling in love with you 무궁화 삼천리 Shall I stay? 화려강산, Would it be a sin? 대한 사람 대한으로 길이 보전하세 If I can't help, 남산 위에 저 소나무, 철갑을 두른 듯 falling in love바람서리 불변함은 우리 기상일세. with you 무궁화 삼천리 화려강산, 대한 사람 대한으로 길이 보전하세 print() 메소드 충돌 print() 메소드 충돌 print() 메소드 충돌 라인 31에 synchronized로 선언한 경우 라인 31에 synchronized를 생략한 경우

wait()-notify()를 이용한 스레드 동기화 공유 데이터로 두 개 이상의 스레드가 데이터를 주고 받을 때 producer-consumer문제 동기화 메소드 wait() : 다른 스레드가 notify()를 불러줄 때까지 기다린다. notify() : wait()를 호출하여 대기중인 스레드를 깨운다. wait(), notify()는 Object의 메소드

예제 12-6 : wait(), notify()를 이용한 바 채우기 다음 설명과 같이 작동하는 스윙 프로그램을 작성하라. 아래 그림에는 스레드를 가진 bar가 있다. 아무 키나 누르면 bar에 마젠타색이 오른쪽으로 1/100씩 채워진다. 가만히 있으면 스레드에 의해 0.1초 간격으로 bar의 마젠타색을 1/100씩 감소시킨다. 키를 빨리 누르지 않으면 스레드의 감소 속도를 이기지 못한다. bar는 JLabel을 상속받은 MyLabel로 작성하고 MyLabel의 paintComponent() 메소드가 bar를 마젠타색으로 채우도록 하라. 초기 화면 키를 반복하여 빨리 누른 화면

예제 12-6 정답 public class TabAndThreadEx extends JFrame { MyLabel bar = new MyLabel(100); TabAndThreadEx(String title) { super(title); this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); Container c = getContentPane(); c.setLayout(null); bar.setBackground(Color.ORANGE); bar.setOpaque(true); bar.setLocation(20, 50); bar.setSize(300, 20); c.add(bar); c.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { bar.fill(); } }); setSize(350,200); setVisible(true); c.requestFocus(); ConsumerThread th = new ConsumerThread(bar); th.start(); // 스레드 시작 public static void main(String[] args) { new TabAndThreadEx( "아무키나 빨리 눌러 바 채우기"); import javax.swing.*; import java.awt.*; import java.awt.event.*; class MyLabel extends JLabel { int barSize = 0; // 바의 크기 int maxBarSize; MyLabel(int maxBarSize) { this.maxBarSize = maxBarSize; } public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.MAGENTA); int width = (int)(((double)(this.getWidth())) /maxBarSize*barSize); if(width==0) return; g.fillRect(0, 0, width, this.getHeight()); synchronized void fill() { if(barSize == maxBarSize) { try { wait(); } catch (InterruptedException e) { return; } barSize++; repaint(); // 바 다시 그리기 notify(); synchronized void consume() { if(barSize == 0) { try { wait(); } catch (InterruptedException e) { return; } } barSize--; repaint(); // 바 다시 그리기 notify(); class ConsumerThread extends Thread { MyLabel bar; ConsumerThread(MyLabel bar) { this.bar = bar; public void run() { while(true) { sleep(200); bar.consume();