Archive

Java Day 23 스레드

|

Java Day 23 스레드


  1. Thread

    • Multi-Tasking
      • 프로세스(Process)란 운영체제에서 실행중인 하나의 프로그램
      • 멀티 프로세스(Multi-Process) : 두 개 이상의 프로세스가 실행되는 것
      • 멀티 태스킹(Multi-Tasking) : 두 개 이상의 프로세스를 실행하여 일을 처리하는 것
    • Multi-Thread
      • 스레드(Thread)란 프로세스 내에서 실행되는 세부 작업 단위
      • 멀티 스레드(Multi-Thread)란 하나의 프로세스에서 여러 개의 스레드가 병행처리 되는 것
      • 멀티 스레드로 동작하는 스레드의 예외는 다른 스레드나 프로세스 자체에 영향을 끼칠 우려가 있기 때문에 예외 처리를 잘 해야한다
    • Life cycle of a Thread
      • 스레드는 Thread 객체가 생성되면 생명주기를 갖게 된다
      • New - 스레드가 생성된 상태
      • Runnable - 객체 생성 후 start() 메소드 호출시 Runnanle 상태로 이동
      • Running - Runnable 상태에서 스레드 스케쥴러에 의해 Running 상태로 이동
      • Blocked - 스레드가 다른 특정한 이유로 Running에서 Blocked 상탤로 이동
      • Dead - 스레드가 종료되면 그 스레드는 다시 시작 할 수 없게 된다
    • Thread 생성 방법
      1. Thread를 상속 받아서 클래슬 만들기
      2. Runnable 인터페이스를 상속받아서 클래스 만들기


  2. Thread Class 생성자와 메소드

    • 생성자

    생성자

    • 메소드

    메소드


  3. Thread 구현

    • Thread class 상속받아서 구현
    // Thread를 상속받아 나 자신이 thread가 됨
    public class SingleThreadEx extends Thread {
    	private int[] temp;
    	public SingleThreadEx(String threadName) {
    		super(threadName);
    		temp = new int[10];
    		for(int start = 0; start<temp.length; start++) {
    			temp[start] = start;
    		}
    	}
    	public void run() {
    		for(int start : temp) {
    			try {
    				sleep(1000);
    			} catch(InterruptedException ie) {
    				ie.printStackTrace();
    			}
    			System.out.printf("스레드 이름 : %s ,", currentThread().getName());;
    			System.out.printf("temp value : %d %n", start);
    		}
    	}	
    	public static void main(String[] args) {
    		SingleThreadEx st = new SingleThreadEx("첫번째");
    		st.start();
    	}
    }
    
    • Runnable interface 상속받아서 구현
    // Runnable이기 때문에 Thread 객체를 만들어 그 안에 넣어 사용해야함 
    public class SingleRunnableEx implements Runnable {
    	private int temp[];
    	public SingleRunnableEx() {
    		temp = new int[10];
    		for(int start=0; start<10; start++) {
    			temp[start] = start;
    		}
        }
    	@Override
    	public void run() {
    		for(int start : temp) {
    			try {
    				Thread.sleep(1000);
    			} catch(InterruptedException ie) {
    				ie.printStackTrace();
    			}
    			System.out.printf("스레드 이름 : %s,", Thread.currentThread().getName());
    			System.out.printf("temp value : %d %n", start);
    		}
    	}
    	public static void main(String[] args) {
    		SingleRunnableEx srt = new SingleRunnableEx();
    		Thread t = new Thread(srt, "첫번째");
    		t.start();
    	}
    }
    


  4. join() 메소드

    • join() 메소드는 join() 메소드를 호출한 스레드가 종료할 때까지 현재의 스레드가 기다리게 해준다.
    class MyRunnable implements Runnable {
    	@Override
    	public void run() {
    		System.out.println("Run");
    		first();
    	}
    	public void first() {
    		System.out.println("First");
    		second();
    	}
    	public void second() {
    		System.out.println("Second");
    	}
    }
       
    public class JoinEx {
    	public static void main(String[] args) {
    		System.out.println(Thread.currentThread().getName()+" start!");
    		Runnable r = new MyRunnable();
    		Thread myThread = new Thread(r);
    		myThread.start();
    		try {
    			myThread.join(); // main이 끝나기 전 start() 실행
    		} catch(InterruptedException ie) {
    			ie.printStackTrace();
    		}
    		System.out.println(Thread.currentThread().getName()+" end!");
    	}
    }
    //main start!와 main end!의 사이에 Run, First, Second가 찍혀있다
    


  5. Thread의 종류

    1. User Thread : main의 종료와 상관없이 thread를 계속 실행, setDaemon(false)
    2. Daemon Thread : main 종료시 thread도 같이 종료, setDaemon(true)
    3. setDaemon() 메소드는 반드시 start() 이전에 설정해야 한다
  6. Thread 스케쥴링

    • 우선순위 방식 : 우선순위가 높은 스레드가 실행 상태를 더 많이 가짐
    • 순환할당 방식 : 시간 할당량을 정해서 정해진 시간만큼 실행 후 다른 스레드를 실행
    • 순환할당 방식은 JVM에 의해 정해지기 때문에 코드로 제어 할 수 없다
    • 우선순위 방식은 setPriority(1~10) 메소드로 1~10 까지의 우선순위를 결정 할 수 있다
    • setPriority() 메소드는 반드시 start() 이전에 설정해야 한다
    class CalcThread extends Thread {
    	public CalcThread(String name) {
    		setName(name);
    	}
    	public void run() {
    		for(int i=0; i<1000000; i++) {
    		}
    		System.out.println(getName());
    	}
    }
    public class PriorityEx {
    	public static void main(String[] args) {
    		for(int i=1; i<=10; i++) {
    			Thread thread = new CalcThread("Thread" + i);
    			if (i != 10) {
    				thread.setPriority(Thread.MIN_PRIORITY);
    			} else {
    				thread.setPriority(Thread.MAX_PRIORITY);
    			}
    			thread.start();
    		}
    	}
    }// 우선순위가 높은 Thread10이 가장 먼저 찍힌다
    


  7. 동기화 (synchronized)

    • 임계 영역 : 멀티 스레드상에서 하나의 스레드만 실행 할 수 있는 코드 영역
    • 상호 배제 : 특정 프로세스가 공유 자원을 사용하고 있을때, 다른 프로세스의 접근을 제어하는 기법, 번갈아가며 쓰도록 임계 영역을 유지하는 기법
    • 동기화 메소드와 블록으로 메소드 혹은 블록에 lock을 걸어 다른 스레드가 임계 영역에 들어오지 못하게 막을 수 있다
    • 메소드에 sychhronized 지정어를 걸거나 메소드 안에서 sychhronized 블록을 생성하여 동기화 할 수 있다
    • 동기화된 스레드는 wait(), notify(), notifyAll() 메소드로 스레드간 통신을 할 수 있다 (synchronized 블록에서만 사용 가능)
    class ATM implements Runnable {
    	private long depositMoney = 10000;
    	public void run() {
    		synchronized(this) { // 동기화
    			for(int i=0; i<10; i++) { // 임계 영역
    				if(getDepositMoney() <= 0) break;
    				withDraw(1000);
    				if(getDepositMoney() == 2000 || getDepositMoney() == 4000 || 
    						getDepositMoney() == 6000 || getDepositMoney() == 8000) {					
    					try {
    						this.wait();
    					} catch(InterruptedException ie) {
    						ie.printStackTrace();
    					}
    				} else {
    					this.notify();
    				}
    			}
    		}
    	}
    	public void withDraw(long howMuch) {
    		if(getDepositMoney() > 0) {
    			depositMoney -= howMuch;
    			System.out.println(Thread.currentThread().getName()+", ");
    			System.out.printf("잔액 : %,d 원 %n", getDepositMoney());
    		} else {
    			System.out.println(Thread.currentThread().getName()+", ");
    			System.out.println("잔액이 부족합니다.");
    		}
    	}
    	public long getDepositMoney() {
    		return depositMoney;
    	}
    }
    public class SynchronizedEx {
    	public static void main(String[] args) {
    		ATM atm = new ATM();
    		Thread mother = new Thread(atm, "mother");
    		Thread son = new Thread(atm, "son");
    		mother.start();
    		son.start();
    	}
    }
    /* 출력 결과
    잔액 : 9,000 원 
    mother, 
    잔액 : 8,000 원 
    son, 
    잔액 : 7,000 원 
    son, 
    잔액 : 6,000 원 
    mother, 
    잔액 : 5,000 원 
    mother, 
    잔액 : 4,000 원 
    son, 
    잔액 : 3,000 원 
    son, 
    잔액 : 2,000 원 
    mother, 
    잔액 : 1,000 원 
    mother, 
    잔액 : 0 원 
    */
    





참고 자료


이것이자바다

자바프로그래밍100% 실전가이드

KG아이티뱅크 자바 강의자료