메모리에 큰 프로세스를 올리는게 아니라 여러프로세스들의 조각(Thread)를 올려 CPU에게 계속 제공, 처리
원래 하나에 하나의 프로세스만 처리되는데 여러개의 프로세스가 처리되는 것처럼 보이는 것.
자바는 Multi Thread 지원
cmd는 싱글 Thread,cmd에서 eclipse.bat을 실행하면 다른 작업을 못 한다.
Thread 사용된 코드는 종료시간을 측정할 수 없다.
Runnable interface, Thread class로 Thread 사용가능
Runnable interface는 생명주기를 관리할 수 없음
Thread class는 생명주기 관리 method 존재
자바는 선점형 Thread
작업관리자가 필요없음
간단하게 구현되고 사용가능
호출되는 시점에 줄을 서서 선점 순서대로 처리가 됨.
또다른 방식은 시분할 OS
작업관리자의 역할이 매우 중요
작업관리자가 시간을 프로세스들에게 분배, CPU를 점유가능케 함
Thread가 CPU를 점유하고선 끝나지 않는 상태 Deadlock
CPU를 점유하는 Thread를 강제로 뜯어내는 것 = Interrupt
전원을 뽑는 것도 interrupt의 일부
작업관리자에서 프로세스강제 종료
cmd에서 ^c로 종료 등
Thread 생명주기
선점형 Thread는 누가 먼저 실행될지 모름, start()로 running
Field로 우선순위를 바꿀 수 있으나 잘 바꾸진 않는다.(통제불가)
yield() 를 사용하여 순서를 양보할 수 있다.
sleep이란 메서드로 Thread를 block상태로 만들 수 있다.
Thread가 block상태가 안되어 InterruptedException 발생가능
millis만큼 쉬다가 자동으로 Running 상태로 돌아옴
wait은 Thread를 쓰든 쓰지 않든 사용가능, sleep과 동일하게 Thread block가능
Object클래스에 존재, wait으로 멈춘 Thread는 notify 메서드를 이용하여 직접 깨워야 한다.
하나만 깨울 땐 notify, 모든 Thread를 깨울 땐 notifyAll 메서드를 이용한다.
stop()메서드로 Thread를 중지시킬 수 있으나 중지시키면 사용중이던 자원이 불완전한 상태로 남겨지기 때문에 사용안하는 deprecated method
Thread class를 상속받아 Thread 사용
start가 호출되어야 Thread가 시작함
start()호출하면 run() 호출, Override된 method가 호출됨.
// 1. Thread 상속public class Test extends Thread { ... }// 2. run method Override@Overridepublic void run() { // 3. Thread로 처리되어야할 코드(동시실행 코드)}// 4. 객체 생성Test t = new Test();// 5. start method 호출t.start();
// Thread 클래스를 상속받아서 Thread 사용.// 1. Thread 상속public class UseThread extends Thread { // 2. run() Override @Override public void run() { // 3. Thread로 처리되어야할 코드 작성 for(int i =0; i< 1000; i++) { System.out.println("run(), i ------> "+i); } } public static void main(String[] args) { // 4. 객체 생성 UseThread ut = new UseThread(); // 5. 부모클래스인 Thread가 가지고 있는 start() 호출 ut.start(); for(int i =0; i< 1000; i++) { System.out.println("main(), i ======> "+i); } }}
실행순서는 스케줄링에 따라 매번 달라진다.
항상 번갈아가며 순서대로만 실행되지 않음
// ut.start(); ut.run();
Thread를 start()로 실행시키지 않고 run()을 실행시키면 Thread로 동작하지 않는다
run()이 모두 끝나고 main메소드 안에 반복문이 실행된다.
Runnable interface 구현하여 Thread 사용
// 1. Runnable 구현public class Test implements Runnable { ... }// 2. run method Override@Overridepublic void run() { // 3. Thread로 처리되어야할 코드 작성(동시실행 코드)}// 4. 객체 생성Test t = new Test();// 5. Thread 생성, Runnable interface는 start()가 없기 때문에Thread th = new Thread(t);// 6. start method 호출// has-a 관계의 클래스가 Override한 run() 호출됨th.start();
// Runnable interface를 구현하여 Thread를 사용// 1. Runnable 구현public class UseRunnable implements Runnable { // 2. run() Override @Override public void run() { // 3. Thread로 동작해야하는 코드 작성 for(int i=0; i<1000; i++) { System.out.println("run(), i -----> "+i); } } public void test() { for(int i=0; i<1000; i++) { System.out.println("test(), i =====> "+i); } } public static void main(String[] args) { // 4. Runnable을 구현한 클래스를 객체화 UseRunnable ur = new UseRunnable(); // 5. Thread 객체와 Runnable 구현 객체를 has-a 관계로 설정 Thread th = new Thread(ur); // 6. Thread에 있는 start() 호출 th.start(); // has-a 관계가 설정되지 않으면 Thread의 run() 호출됨. ur.test(); }}
Thread를 사용하면 끝나는 시간을 구할 수 없다.
main method가 끝나도 다른 Thread는 계속 살아서 처리할 수 있기 때문에
public static void main(String[] args) { long st = System.currentTimeMillis(); // 4. Runnable을 구현한 클래스를 객체화 UseRunnable ur = new UseRunnable(); // 5. Thread 객체와 Runnable 구현 객체를 has-a 관계로 설정 Thread th = new Thread(ur); // 6. Thread에 있는 start() 호출 th.start(); ur.test(); long et = System.currentTimeMillis(); System.out.println((et-st)+"ms");}
Thread는 구현하는 방식을 더 많이 쓴다.
상속은 하나밖에 할 수 없기 때문
Sleep 사용
Thread클래스 sleep method는 static.
// running 상태에서 block 상태로 상태 이전시키는 sleep method(생명주기)public class UseSleep implements Runnable { @Override public void run() { for(int i=0; i<10 ; i++) { System.out.println("2 * "+i+" = "+ (2*i)); // running 상태 try { Thread.sleep(500); // block 상태 } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { UseSleep us = new UseSleep(); Thread th = new Thread(us); th.start(); }}
자바에선 main메소드도 Thread로 처리되기 때문에 Thread.sleep()은 어디서나 사용 가능하다.
// sleep을 사용한 로딩출력 예제public class UseSleep implements Runnable { @Override public void run() { System.out.print("loading"); Random r = new Random(); for(int i=0; i<15; i++) { System.out.print(" . "); try { Thread.sleep(100*r.nextInt(10)+1); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print("finish"); } public static void main(String[] args) { UseSleep us = new UseSleep(); Thread th = new Thread(us); th.start(); }}