페이지

2015. 1. 15.

[JAVA] Day8.쓰레드(Thread)

쓰레드



멀티테스킹(MultiTasking)


 - Process란 OS에서 실행중인 하나의 Program을 말한다.
 - Multi Process란 두 개 이상의 Process가 실행되는 것을 말한다.
 - MultiTasking이란 두 개 이상의 Process를 실행하여 일을 처리하는 것을 말한다.

>> 여러명이서 같이 일을 하는 것으로 보면 쉬움

멀티쓰레드(Multi Thread)


 - Thread란 Process 내에서 실행되는 세부 작업 단위이다.
 - Multi Thread란 하나의 Process에서 여러 개의 Thread가 병행적으로 처리되는 것을 말한다.

>> 동시에 2, 3가지 일을 하는 것


쉽게 말하면
클래스 = 프로그램
메서드 = 프로세스


멀티 쓰레드와 싱글 쓰레드


멀티 쓰레드라고 보면 씽글 쓰레드의 80퍼센트 정도의 효율이 있다.
20퍼센트는 스위칭 타임이나 로드 하는데 오버헤드가 생겨서 손실이 생김



Thread의 생성


 - Thread class를 상속 받는 방법



class ThreadEx extends Thread
{
    public void run()
    {

    }
    public static void main(String[] args)
    {
        ThreadEx th1 = new ThreadEx();
        th1.start();
    }
}






 - Runnable Interface를 구현하는 방법



class ThreadEx implements runnable
{
    public void run()
    {

    }
    public static void main(String[] args)
    {
        ThreadEx th1 = new ThreadEx();
        Thread t = new Thread(th1);
        t.start();
    }
}


>> 이 둘은 동작하는 방법은 동일하다.



문법적으로 자유로운 Runnable로 구현하여 사용하자.
(클래스는 단일 상속만 하므로)

그러나.....

실직적으로는 쓰레드 클래스를 상속 받아서 사용한다.
(많은 메서드를 만들어 놓아서 굳이 Runnable가 필요없기 때문이다.)







Thread class의 주요 method


 - sleep(long millis) : millis에 지정된 시간만큼 대기한다.
 - getName() : Thread의 이름을 반환한다.
 - setName(string name) : Thread의 이름을 지정한다.
 - start() : Thread를 시작시킨다.
 - getPriority() : Thread의 우선순위를 반환한다.
 - setPriority(int newPriority) : Thread의 우선순위를 지정한다.
 - join() : 현재 Thread는 join()메서드를 호출한 Thread가 종료할때까지 기다리게 된다. join()을 호출한 Thread가 종료할 때까지 현재의 Thread를 기다리게 된다.
 - yield() : 수행중인 Thread 중 우선순위가 같은 다른 Thread에게 제어권을 넘긴다.
 - currentThread() : 현재 수행되는 Thread 객체를 리턴한다.




exit(0) : 정상종료
exit(1) : 강제종료



스레드 예제

import javax.swing.JOptionPane;

class ThreadEx
{
    static boolean inputCheck = false;
    public static void main(String[] args) throws Exception
    {
        ThreadEx_1 th1 = new ThreadEx_1();
        ThreadEx_2 th2 = new ThreadEx_2();
        th1.start();
        th2.start();
    }
}

class ThreadEx_1 extends Thread
{
    public void run()
    {
        System.out.println("10초 안에 값을 입력해야 합니다.");
        String input = JOptionPane.showInputDialog("아무 값이나 입력하세요.");
        ThreadEx.inputCheck = true;
        System.out.println("입력값은" + input +"입니다.");
    }
}

class ThreadEx_2 extends Thread
{
    public void run()
    {
        for (int i=10;i>=0;i--)
        {
            if (ThreadEx.inputCheck)
                return;
            System.out.println(i);
            try
            {    sleep(1000);    }
            catch (InterruptedException e)
            {                    }
        }
        System.out.println("10초 동안 값이 입력되지 않아 종료합니다.");
        System.exit(0);
    }
}








Thread의 우선순위


 - Thread class에서는 Thread의 우선순위를 부여하는 setPriority 메소드를 제공한다.
 - 멈추는 우선순위가 아니고 같이 처리하기는 하지만 비중을 조금 더 늘려준다.
 - 6:4 이런식으로, 근데 사실상 체감하지 못함 (둘 다 처리되고 있기 때문에)






Thread 클래스의 우선 순위를 정하는 맴버변수


 - MAX_PRIORITY : Thread가 가질 수 있는 최대 우선 순위값(10)
 - NORM_PRIORITY : Thread가 가질 수 있는 기본 순위값(5)
 - MIN_PRIORITY : Thread가 가질 수 있는 최소 우선 순위값(1)
 - 디폴트는 5
setPriority(Thread.MAX_PRIORITY)















class ThreadEx9 {
    public static void main(String args[]) {
        ThreadEx9_1 th1 = new ThreadEx9_1();
        ThreadEx9_2 th2 = new ThreadEx9_2();
        th2.setPriority(7);
        System.out.println("Priority of th1(-) : " + th1.getPriority() );
        System.out.println("Priority of th2(|) : " + th2.getPriority() );
        th1.start();
        th2.start();
    }}
class ThreadEx9_1 extends Thread {
    public void run() {
        for(int i=0; i < 3; i++) {
            System.out.print("-");
            for(int x=0; x < 10; x++);
        }}}
class ThreadEx9_2 extends Thread {
    public void run() {
        for(int i=0; i < 3; i++) {
            System.out.print("|");
            for(int x=0; x < 100; x++);
        }}}









데몬 스레드


 - 메인에 귀속된 쓰레드(메인이 끝나면 쓰레드도 종료)







 class ThreadEx11 implements Runnable  {
    static boolean autoSave = false;
    public static void main(String[] args) {
        Thread t = new Thread(new ThreadEx11());
        t.setDaemon(true);        // 이 부분이 없으면 종료되지 않는다.
        t.start();
        for(int i=1; i <= 20; i++) {
            try{
                Thread.sleep(1000);
            } catch(InterruptedException e) {}
            System.out.println(i);           
            if(i==5)
                autoSave = true;
        }
        System.out.println("프로그램을 종료합니다.");
    }
    public void run() {
        while(true) {
            try {
                Thread.sleep(3 * 1000);    // 3초마다
            } catch(InterruptedException e) {}   
            // autoSave의 값이 true이면 autoSave()를 호출한다.
            if(autoSave) {
                autoSave();
            }}}
    public void autoSave() {
        System.out.println("작업파일이 자동저장되었습니다.");
    }}













쓰레드 제어








join() : 메인이 쓰레드 1 2 가 종료될떄까지 기다리는것...
종료가 되면 메인이 실행

무한정 기달릴수 있는 인터럽트에 걸릴수도 있당.

따라서 예외 처리가 필수임..

 class ThreadEx13 {
    static long startTime = 0;
    public static void main(String args[]) {
        ThreadEx13_1 th1 = new ThreadEx13_1();
        ThreadEx13_2 th2 = new ThreadEx13_2();
        th1.start();
        th2.start();
        startTime = System.currentTimeMillis();
        try {
               th1.join();    // th1의 작업이 끝날 때까지 기다린다.
            th2.join();    // th2의 작업이 끝날 때까지 기다린다.

        } catch(InterruptedException e) {}
        System.out.print("소요시간:" + (System.currentTimeMillis()
                                                           - ThreadEx13.startTime));
    } }
class ThreadEx13_1 extends Thread {
    public void run() {
        for(int i=0; i < 300; i++) {
            System.out.print("-");
        }} }
class ThreadEx13_2 extends Thread {
    public void run() {
        for(int i=0; i < 300; i++) {
            System.out.print("|");
        }} }







예제 16번

class ThreadEx
{
    public static void main(String[] args) throws Exception
    {
        RunImpEx16 r = new RunImpEx16();
        Thread th1 = new Thread(r, "*");
        Thread th2 = new Thread(r, "**");
        Thread th3 = new Thread(r, "***");

        th1.start();
        th2.start();
        th3.start();
        try
        {
            Thread.sleep(2000);     //메인이 2초 멈춘다.
            th1.suspend();        //서스펜드는 일시정지
            Thread.sleep(2000);
            th2.suspend();
            Thread.sleep(3000);
            th1.resume();        //1번 재실행
            Thread.sleep(3000);
            th1.stop();        //1번 종료
            th2.stop();
            Thread.sleep(2000);
            th3.stop();
        }
        catch (InterruptedException e)
        {
        }
    }//main
}
class RunImpEx16 implements Runnable
{
    public void run()
    {
        while(true)
        {
            System.out.println(Thread.currentThread().getName());
            try
            {
                Thread.sleep(1000);
            }
            catch (InterruptedException e)
            {
            }
        }
    }//run
}

//컨드롤은 메인에서 하고 스레드에서 기능을 동작한당.
//웹에서는 환경 자체가 멀티쓰레드라서 잘쓰이지는 않는다.
//응용프로그램에서 쓰이는데 그닥...








멀티쓰레드 쓴다고 다 좋은건 아니다.

단지 동시에 여러개의 일을 할 수 있는 장점과 효율 사이에 적절하게 사용해야함