ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java - Thread
    Java 2018. 1. 30. 14:57
    반응형
    // Thread는 어떤 program을 실행 하게 해주는 원동력이다
    // 대표적으로 main(String[] args)로 실행 한다.

    // process는 1개 이상의 thread로 구성되어 있다.
    // process는 thread로 구성 된다.
    // 메모리 공유 부분에서 process는 메모리 공유가 안되지만,
    // Thread는 메모리 공유가 된다.


    // main method는 main thread를 생성 한다.
    // 처리가 버거우면 work thread를 생성할 수 있다.
    // 이것을 multi thread라 한다.


    // Runnable Interface, Thread Class 상속으로 생성할 수 있다.



    < Runnable >

    public class Main {

        public static void main(String[] args) {
            
            // 워크 스레드 생성 - Runnable 객체를 구현 받는 방법
            Runnable job = new Job(); // 1.쓰레드가 해야할 일 생성
            Thread work = new Thread(job); // 2. 그 일을 해야할 스레드 생성
            work.start(); // 3. 해당 스레드 시작
            
            /*메인 Thread가 하는 일*/
            for(int i = 1 ; i <= 5; i++) {
                System.out.println("i의 값은 : "+i);
                try {
                    Thread.sleep(500); // 0.5초간 차
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
            // 워크 스레드가 메인 스레드 아래있으면 메인스레드부터 실행되고 워크 스레드가 실행된다.
            // 워크 스레드가 위에 있으면 메인스레드와 같이 일한다.
            
        }

    }


    public class Job implements Runnable {

        @Override
        public void run() { // Thread 실행시 해야만 하는 일
            for(int i = 1 ; i <= 5; i++) {
                System.out.println("work thread -> i의 값은 : "+i);
                try {
                    Thread.sleep(500); // 0.5초간 차
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }



    < AnonyMous Runnable >

    public class AnonyMain {

        public static void main(String[] args) throws InterruptedException {
            
            // 워크 스레드 생성
            Thread th = new Thread(new Runnable() { // 익명 객체로 따로 만들어버린다.
                
                @Override
                public void run() {
                    for(int i = 1 ; i <= 5; i++) {
                        System.out.println("work thread -> i의 값은 : "+i);
                        try {
                            Thread.sleep(500); // 익명 객체는 한번쓰고 말것이기때문에 누군가 한테 throws를 할 수 없다.
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            
            th.start();
            
            // 메인스레드 수행
            for(int i = 1 ; i <= 5; i++) {
                System.out.println("i의 값은 : "+i);
                Thread.sleep(500); // 0.5초간 차
            }
            
        }

    }


    < Thread >


    public class Job extends Thread {

        @Override
        public void run() { // Thread 실행시 해야만 하는 일
            for(int i = 1 ; i <= 5; i++) {
                System.out.println("work thread -> i의 값은 : "+i);
                try {
                    Thread.sleep(500); // 0.5초간 차
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }



    public class Main {

        public static void main(String[] args) {
            
            // 워크 스레드 생성 - Runnable 객체를 구현 받는 방법
            Thread job = new Job(); // 1.쓰레드가 해야할 일 생성
            job.start(); // 2. 해당 스레드 시작
            
            /*메인 Thread가 하는 일*/
            for(int i = 1 ; i <= 5; i++) {
                System.out.println("i의 값은 : "+i);
                try {
                    Thread.sleep(500); // 0.5초간 차
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
        }

    }


    < Name >


    public class WorkThread extends Thread {

        @Override
        public void run() {
            
            for(int i=1;i<=5;i++) {
                System.out.println(getName() + " 스레드가 출력한 내용 : "+i);
    // Thread 자체이기때문에 getName()사용
                 // 스레드 이름 얻어오기
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
        }
        
    }



    public class MainThread {

        public static void main(String[] args) {
            
            Thread th = new WorkThread();
            th.setName("First"); // Thread Name 지정
            th.start();
            
            th = new WorkThread();
            th.setName("Second");
            th.start();
            
            th = new WorkThread();
            th.setName("Third");
            th.start();
            
        }

    }


    Runnable Interface 구현 1. 쓰레드가 해야할 일 생성 - Runnable 객체 생성 2. 그 일을 해야할 스레드 생성 - Thread 생성 3. 해당 스레드 시작 Thread Class 상속 1. 쓰레드가 해야할 일 생성 - 바로 Thread 생성 2. 해당 스레드 시작 둘 다 익명객체 사용 가능
    -> 메모리 관리 가능, 한번만 사용할 때, 객체생성 필요없음






    < Thread Priority >

    // Thread에 순서가 없어서 제어가 어렵다.
    // Thread는 Round robin방식을 사용하기 때문이다.
    // 빨리 일을 끝내면 다음 일을 받는 방식이므로 먼저 시작했다고 먼저 끝나지 않는다.

    Thread Priority -
    // 시작과 동시에 우선순위를 부여하므로 짧은 작업에는 의미가 없다.
    // 우선순위는 1~10까지 줄 수 있다.
    // 우선순위가 같을 경우는 빠른놈이 먼저다.
    // 상수로 값을 대신할 수 있다.
    // 상수 - > Thread.MIN_PRIORITY -> 1
    // Thread.MAX_PRIORITY -> 1
    // Thread.NORM_PRIORITY -> 5
    // 우선순위를 줄 수 있지만, 허술한점이 많아서 잘 사용되지 않는다.


    public class WorkThread extends Thread {

        public WorkThread(String name) {
            setName(name); // 스레드 이름 생성
        }
        
        @Override
        public void run() {
            System.out.println(getName()+" 스레드 시작");
            for(int i=0;i<=100000;i++) {
                // 이 시간동안 작업한다고 가정
            }
            System.out.println(getName()+" 스레드 시작");
        }
        
    }



    public class Main {

        public static void main(String[] args) throws InterruptedException {
            
            // 우선순위는 1~10까지 줄 수 있다.
            // 우선순위가 같을 경우는 빠른놈이 먼저다.
            // 상수로 값을 대신할 수 있다.
            // 상수 - > Thread.MIN_PRIORITY -> 1
            // Thread.MAX_PRIORITY -> 10
            // Thread.NORM_PRIORITY -> 5
            
            for(int i=1; i<=5; i++) {
                Thread th = new WorkThread(i+"번 스레드");
                th.setPriority(i); // 우선순위 지정
                th.start();
    Thread.sleep(1000) // sleep으로 어느정도 구분 지을 수 있다.
            }
            
            // 우선순위로는 제어가 정확히 어렵다.
            // 그래서 정확한 제어를 위해서는 다른 메서드를 제공해 준다.
            
        }

    }




    < Synchronized >


    // Thread는 객체 간의 데이터의 간섭이 일어 나기도 한다.
    // Synchronized는 다른 데이터의 간섭을 막을 수 있다.
    // vector와 비슷

    // Syncronized 방법은 크게 2가지다
    // Syncronized method를 사용 하는 방법과
    // Syncronized block을 사용 하는 방법이 있다.

    public class Computer {
        
        private int score;
        // 컴퓨터를 아무나 쓸 수 있어서 데이터가 뒤섞인다.
        /*public void setScore(int score) {
            this.score = score;
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" : "+this.score);
            // 현재 활성화 되있는 스레드의 이름과 점수
        }*/
        // 컴퓨터에 Lock를 건다.
        // Synchronized 메서드는 한번에 하나의 스레드만 접근 한다.
        public synchronized void setScore(int score) {
            this.score = score;
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" : "+this.score);
            // 현재 활성화 되있는 스레드의 이름과 점수
    }
    // 특정 영역만 접근을 제한한다.
        public void setScore(int score) {
            
            // 이 블럭 부분만 제한해서 실행한다.
            synchronized (this) { // this == Computer
                this.score = score;
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+" : "+this.score);
            }
        }

    }



    public class User1 extends Thread {

        private Computer com;
        
        public User1(Computer com) {
            this.com = com;
            setName("user1");
        }
        
        @Override
        public void run() {
            com.setScore(500);
        }
        
    }


    public class User2 extends Thread {
        private Computer com;
        
        public User2(Computer com) {
            this.com = com;
            setName("user2");
        }
        
        @Override
        public void run() {
            com.setScore(100);
        }

    }



    public class PcRoom {

        public static void main(String[] args) {
            
            Computer com = new Computer();
            
            User1 user1 = new User1(com);
            User2 user2 = new User2(com);
            
            user1.start();
            user2.start();
            
        }

    }




    < Thread State >

    // Thread는 생성부터 종료까지의 값이 된다.
    // getState()를 통해 현재 상태를 알 수 있다.
    // new -> runnable -> 실행 -> terminated

    public class WorkThread extends Thread {

        @Override
        public void run() {
            // 실행
            for(long i=0; i<=10000000; i++) {}
            // 1.5초 휴식
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 실행
            for(long i=0; i<=10000000; i++) {}
        }
        
    }



    import java.lang.Thread.State;

    public class Main {

        private static Thread.State state;
        
        public static void main(String[] args) {
            // 워크 스레드 생성 -> 실행 -> 일시정지 -> 실행 -> 종료
            // 메인스레드에서 정지
            Thread th = new WorkThread();
            
            while(true) {
                state = th.getState();
                System.out.println("work thread state : "+state);
                
                if(state == Thread.State.NEW) {
                    th.start();
                }
                
                // terminated가 되었을때 감시를 멈추고 싶다면?
                if(state == Thread.State.TERMINATED) {
                    break;
                }
                
                // 0.1초 간격으로 감시하고 싶다면?
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
            }
            
        }

    }




    < Thread Control >

    // sleep()은 ms동안 thread를 일시 정지 시킨다. - 제한시간이있다.
    // yield()는 특정 스레드에게 제어권을 양보한다. - 제한시간이없다
    // yield는 다른 thread에게 일을 처리할 길을 터주면서 자신의 일도 수행한다.
    // 자기 자신이 쉬는 의미가 아니라, 다른 스레드도 실행할 수 있는 기회를 양보 하는 것이다.


    public class ThreadA extends Thread {

        boolean stop = false;
        boolean yield = false;
        
        @Override
        public void run() {
            while(!stop) {
                if(yield) {
                    System.out.println("Thread B 에게 양보");
                    Thread.yield();
                }
                System.out.println("Thread A 동작중");
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("Thread A 중지");
        }
        
    }


    public class ThreadB extends Thread {
        
        boolean stop = false;
        boolean yield = false;
        
        @Override
        public void run() {
            while(!stop) {
                if(yield) {
                    System.out.println("Thread A 에게 양보");
                    Thread.yield();
                }
                System.out.println("Thread B 동작중");
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("Thread B 중지");
        }
        
    }


    public class Main {

        public static void main(String[] args) throws InterruptedException {
            
            ThreadA thA = new ThreadA();
            ThreadB thB = new ThreadB();
            
            thA.start();
            thB.start();
            
            thA.yield = true; // A에게 양보하라고 함 -> B동작
            Thread.sleep(500);
            
            thA.yield = false;
            thB.yield = true;
            
            Thread.sleep(500);
            
            thA.stop = true;
            thB.stop = true;
            
        }

    }





    < Join >

    // join은 다른 스레드의 종료를 기다린 후에 실행할 때 사용 한다.
    // 효용성 중요


    public class OperThread extends Thread {

        private int sum;
        
        public int getSum() {
            return sum;
        }
        
        @Override
        public void run() {
            
            for(int i = 1; i <=100; i++) {
                sum += i;
            }
            
        }
        
    }


    public class Main {

        public static void main(String[] args) throws InterruptedException {
            
            OperThread th = new OperThread();
            
            System.out.println("1~100까지의 합은?");
            th.start();
            th.join(); // 일을 시키면 끝날 때 까지 기다려 준다.
            System.out.println("답 : "+th.getSum());
            
        }

    }



    < wait, notify, notifyAll >

    // wait() : 지정한 스레드를 일시 정지 상태로 만든다.
    // notify() : 일시 정지 상태중인 스레드 중 하나를 실행 대기 상태로 바꾼다.
    // notifyAll() : 일시 정지된 모든 스레드를 실행 대기 상태로 만든다.


    public class WorkObj {

        // 한번에 하나의 스레드만 접근 하도록
        // 하나의 스레드가 실행되는 동안 다른 스레드는 일시정지
        // 메서드를 사용하면 해당 스레드는 대기하고 다른 스레드를 깨운다.
        // synchronized는 동시접근 불가
        public synchronized void work() { // synchronized로 하나만 들어오게 한다
            System.out.println(Thread.currentThread().getName()+" 실행 중");
            notify(); // 다른 스레드를 깨워준다.
            try {
                wait(); // 스스로 대기
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
    }


    public class WorkThread extends Thread {

        private WorkObj obj;
        
        public WorkThread(WorkObj obj) {
            this.obj = obj;
        }
        
        @Override
        public void run() {
            for(int i=1; i<5; i++) {
                obj.work();
            }
        }
        
    }


    public class Main {

        public static void main(String[] args) {
            
            WorkObj obj = new WorkObj();
            WorkThread thA = new WorkThread(obj);
            WorkThread thB = new WorkThread(obj);
            
            thA.start();
            thB.start();
            
        }

    }





    반응형

    'Java' 카테고리의 다른 글

    Java - Stop, Interrupt  (0) 2018.01.31
    Java - Wait, Notify  (0) 2018.01.31
    Java - 정규표현식  (0) 2018.01.26
    Java - Stack, Queue  (0) 2018.01.25
    Java - Map  (0) 2018.01.25

    댓글

Designed by Tistory.