[24.04.29] 내일배움캠프 11일차 JAVA TIL - Thread, 모던 자바

2024. 4. 29. 20:50T.I.L

오늘 한 일

  • 5주차 강의 수강
  • 개인과제 레벨 2 마무리

 


수기를 남기기에 앞서 교육 내용이 많아, 평소 헷갈렸던 개념 위주로 T.I.L을 작성했다.

 

기본적으로 지금까지 배운 예제에서는 쓰레드가 1개였다. 이를 싱글 쓰레드 라고 한다.

자바는 기본적으로 main() 메소드를 실행시키면 메인 쓰레드가 시작된다.

싱글 Thread : 프로세스 안에서 한번의 쓰레드가 실행되는 것

 

이 싱글 쓰레드와 반대되는 개념이 멀티 쓰레드이다. 반대로 프로세스 안에 여러개의 쓰레드가 동시 다발적으로 실행되는 것을 말한다. 하나의 프로세스에서 리소스를 공유한다!

 

데드락 : 해당 프로세스가 멀티 쓰레드 일때, 각 쓰레드가 사용하고자 하는 자원이 중복되어 서로의 작업이 종료되기를 무한히 대기하는 상태를 말한다.

 

쓰레드를 사용하는 여러가지 방법

public class Main {
    public static void main(String[] args) {
    	// 임의의 TestThread 클래스를 만들고 쓰레드로 사용 이때 extends Thread 사용
        //TestThread tt = new TestThread();
        //tt.start();
        // 임의의 Runnable 클래스 사용 implements Runnable 사용. run()함수 반드시 작성해야 함
//        Runnable run = new TestRunnable();
//        Thread thread   = new Thread(run);
//        thread.start();

        Runnable task= () ->{
            int sum = 0;
            for(int i=0;i<5;i++){
                sum += i;
                System.out.println("*"+ sum);
            }
            System.out.println(Thread.currentThread().getName() + "최종합 : " + sum);
        };

        Thread thread = new Thread(task);
        thread.setName("thread 1");
        Thread thread2 = new Thread(task);
        thread2.setName("thread 2");

        thread.start();
        thread2.start();
    }
}

 

멀티 쓰레드를 사용하면, 먼저 작성된 코드가 우선적으로 실행되지 않으며, 순서가 정해져 있지 않다.

즉, 멀티 쓰레드의 순서가 관계있을 경우 내가 직접 순서를 지정해주어야 한다.

public class Main {
    public static void main(String[] args) {
        Runnable daemon = () -> {
            for(int i=0;i<5;i++)
                System.out.println("daemon");
        };

        Thread t = new Thread(daemon);
        // Thread를 데몬으로 설정할지 여부
        // 데몬의 우선순위는 다른 쓰레드에 비해 낮다.
        // 즉, 리소스 할당을 조금 받는다.
        // 그래서 for문의 길이가 길면 끝까지 찍히지 않는다
        t.setDaemon(true);

        t.start();

        for(int i=0;i<5;i++)
            System.out.println("task");

    }
}

즉, daemon 함수를 이용하여 우선순위를 뒤로 미룰 수 있다.

 

결과값

task
task
task
task
task 
demon
demon
demon
demon
demon

 

 

daemon은 가장 뒷순위로 미루는 것만 가능하지만, 멀티쓰레드가 2개인 경우가 있는게 아니니 우선순위를 정하는 Priorityㅇ와 관련된 함수를 알아야 한다.

 

public class Main {
    public static void main(String[] args) {
        Runnable task = () -> {
            for(int i=0;i<5;i++)
                System.out.println("%");
        };

        Runnable task2 = () -> {
            for(int i=0;i<5;i++)
                System.out.println("&");
        };

        Thread t = new Thread(task);
        t.setPriority(8);
        int threadpriority = t.getPriority();
        System.out.println("threadPriority"+threadpriority);

        Thread t2 = new Thread(task2);
        t2.setPriority(2);

        t.start();
        t2.start();

    }
}

여기서 우선순위는 클 수록 먼저 실행된다.

최대 우선순위 : 10 / 최소 우선순위 : 1 / default 우선순위 : 5

1~10까지 사용자가 우선순위를 정할 수 있다.

해당 우선순위는 OS가 아니라 JVM에서 설정한 우선순위이다.

 

 

해당 코드는 thread를 그룹화하여 interrupt로 빠져나오는 구문이다.

public class Main {
    public static void main(String[] args) {
        Runnable task = () -> {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    break;
                }
            }
            System.out.println(Thread.currentThread().getName() + " Interrupted");
        };

        // ThreadGroup 클래스로 객체를 만듭니다.
        ThreadGroup group1 = new ThreadGroup("Group1");

        // Thread 객체 생성시 첫번째 매개변수로 넣어줍니다.
        // Thread(ThreadGroup group, Runnable target, String name)
        // Thread의 생성자가 여러개이기때문에 인자의 갯수가 다양
        Thread thread1 = new Thread(group1, task, "Thread 1");
        Thread thread2 = new Thread(group1, task, "Thread 2");

        // Thread에 ThreadGroup 이 할당된것을 확인할 수 있습니다.
        System.out.println("Group of thread1 : " + thread1.getThreadGroup().getName());
        System.out.println("Group of thread2 : " + thread2.getThreadGroup().getName());

        thread1.start();
        thread2.start();

        try {
            // 현재 쓰레드를 지정된 시간동안 멈추게 합니다.
            Thread.sleep(5000);// 5 sec
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // interrupt()는 일시정지 상태인 쓰레드를 실행대기 상태로 만듭니다.
        group1.interrupt();

    }
    /*
     한번 실행되는데 1초가 걸리므로, 5초 이전 즉 4번만 실행됨
     */
}

interrupt와 sleep를 while문을 이용해 적절히 사용하면 오류 없이 사용 가능하다.