Thread (쓰레드)

최준호·2021년 10월 29일
0

java

목록 보기
18/25

프로세스와 쓰레드

프로세스(process)
OS로부터 실행에 필요한 자원(메모리)를 할당 받은 프로그램이다.
프로그램을 수행하는데 필요한 데이터와 메모리 등의 자원 그리고 쓰레도로 구성되어있다.
프로세스에서는 최소 하나 이상의 쓰레드가 존재하며, 둘 이상의 쓰레드를 가진 프로세스를 멀티 프로세스라고 한다.

쓰레드(Thread)
프로세스에서 작업을 처리하는 일꾼이라고 생각하면 쉽다.

멀티 태스킹과 멀티 쓰레딩

멀티 태스킹
우리가 사용하는 OS에서 여러 개의 프로세스가 동시에 실행할 수 있느 기능을 지원하는데 이를 멀티 태스킹이라 한다.

멀티 쓰레딩
프로세스도 마찬가지로 프로세스 내에 여러 쓰레드가 동시에 작업을 수행할 수 있는데 이를 멀티 쓰레딩이라 한다.

쓰레드의 구현과 실행

일반적으로 쓰레드를 구현하기 위해서는 Thread 클래스를 직접 상속 받는 방법과 Runnable 인터페이스를 구현하는 방법 2가지가 존재한다. 둘 중에 어느 것을 선택해도 되지만 Thread 클래스를 직접 상속받게 되면 다른 클래스를 상속받지 못하기 때문에 일반적으로 Runnable 인터페이스를 구현하는 방법을 사용한다. 이렇게 인터페이스를 구현하는 방법은 재사용성을 높이고 코드의 일관성을 유지할 수 있기 때문에 더 객체지향적이라고 할 수 있다.

class MyThread implement Runnable{
	public void run(){//실행 내용}
}

Runnable 인터페이스는 오직 run()만 정의되어 있는 간단한 인터페이스다. 우리가 구현해야 할일은 run()의 실행 내용을 정의하는 것이 전부이다.

class ThreadEx1{
	public static void main(String args[]){
    	ThreadEx1_1 t1 = new TreahdEx1_1();	//Thread를 상속받음
        
        Runnable r = new ThreadEx1_2();	//Runnable 구현
        Thread t2 = new Thread(r);
        
        t1.start();
        t2.start();
    }
}

Thread 클래스를 상속받은 경우 Runnable 인터페이스를 구현한 경우의 인스턴스를 생성하는 방법이 다르다. Thread 클래스를 상속받은 경우 인스턴스를 바로 생성하면 되지만 Runnable 인터페이스를 구현한 경우 Runnable 인터페이스를 구현한 클래스의 인스턴스를 생성한 다음, 이 인스턴스를 Thread 클래스의 생성자 매개변수로 제공해야한다.

start()와 run()

쓰레드를 실행하는 start()와 쓰레드를 구현했을 때 우리가 구현하는 부분인 run()의 차이는 무엇일까?

run()
run()은 단순히 우리가 구현한 부분의 로직을 실행시키는 부분이다.
start()
start()는 새로운 쓰레드가 작업을 실행하는데 필요한 호출스택(call stack)을 생성한 다음에 run()을 호출하여 생성된 호출 스택에 가장 먼저 run()을 올라가게 한다. 이렇기 때문에 우리는 start()를 할때마다 새로운 호출스택이 생성되고 해당 쓰레드가 종료될 때 사용된 호출스택은 소멸한다.

싱글과 멀티 쓰레드

1번 작업과 2번작업을 싱글 쓰레드와 멀티 쓰레드로 실행 시켰을 때 컴퓨터는 어떻게 처리하게 되는 걸까? 싱글 쓰레드의 경우 1번 작업을 모두 완료한 후 2번 작업을 시작하고 멀티 쓰레드의 경우 1번 작업과 2번 작업을 번갈아가면서 실행하게 된다. 2개의 작업을 1개의 쓰레드로 실행했을 때보다 2개의 쓰레드로 작업했을 때 더 빠르게 연산할 거라고 생각하지만 결과적으로는 1개의 쓰레드로 실행하는 것이 더 빠른데 그 이유는 멀티 쓰레드는 쓰레드간의 작업 전환(context switching)의 시간이 소요되기 때문이다.

싱글 쓰레드

public class Test {
    public static void main(String[] args){
        //싱글 쓰레드
        long startTime = System.currentTimeMillis();
        for(int i=0; i<300; i++){
            System.out.printf("%s", new String("ㅡ"));
        }
        System.out.println("소요 시간 : "+(System.currentTimeMillis() - startTime));

        for(int i=0; i<300; i++){
            System.out.printf("%s", new String("ㅣ"));
        }
        System.out.println("소요 시간 : "+(System.currentTimeMillis() - startTime));
    }
}

멀티(2개) 쓰레드

public class Test {
    static long startTime = 0;
    public static void main(String[] args){
        //멀티 쓰레드
        Thread1 th1 = new Thread1();
        th1.start();
        startTime = System.currentTimeMillis();
        for(int i=0; i<300; i++){
            System.out.printf("%s", new String("ㅡ"));
        }
        System.out.println("소요 시간 : "+(System.currentTimeMillis() - startTime));
    }
}
class Thread1 extends Thread{
    @Override
    public void run() {
        for(int i=0; i<300; i++){
            System.out.printf("%s", new String("ㅣ"));
        }
        System.out.println("소요 시간 : "+(System.currentTimeMillis() - Test.startTime));
    }
}

다음 코드를 직접 실행시키면

싱글 쓰레드

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
소요 시간 : 23
ㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣ
소요 시간 : 40

멀티(2개) 쓰레드

ㅡㅡㅡㅡㅡㅡㅡㅣㅣㅣㅣㅣㅣㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅣㅣㅣㅣㅣㅣㅣㅣㅡㅡㅡㅡㅡㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
소요 시간 : 31
소요 시간 : 29

결과를 얻는데... 아마 책의 내용과 다르게 멀티 쓰레드가 더 빠른 이유는 최근 컴퓨터의 성능이 많이 발전해서 그런거 같다... 그래서 node나 script 언어류의 비동기 처리가 대세가 되는 거겠지... 라는 개인적인 생각이다. 그리고 아마 자신의 cpu 성능을 넘어가는 쓰레드의 갯수가 처리되면 싱글이 멀티보다 빠르게 종료시킬 것이다.

여기서 우리가 봐야할 점은 싱글 쓰레드의 경우 하나의 처리가 종료된 후 다음 처리가 시작된다는 점과 멀티 쓰레드의 경우 두개의 처리를 번갈아가면서 처리가 된다는 점을 눈여겨 보자!

멀티 쓰레드를 사용하는 경우

위의 결과로는 멀티 쓰레드를 사용하는 것이 항상 좋은거 같지만 자신의 cpu 성능을 넘어가는 경우는 싱글이 처리가 빠르다. 그럼 멀티 쓰레드를 사용하는 경우는 어떤 경우에 사용하는 편이 좋을까?

두 쓰레드가 서로 다른 자원을 사용하는 작업의 경우 멀티 쓰레드 프로세스가 훨씬 효율적이다. 예를 들면 사용자로부터 데이터를 입력 받는 동안 연산을 함께 진행하는 경우, 네트워크로 파일을 주고 받는 작업, 프린터로 파일을 출력하는 작업과 같이 외부기기와의 입출력을 필요로 하는 경우가 이에 해당한다. 사용자 입력의 경우 사용자가 입력을 하는 동안 다른 쓰레드에서는 연산의 작업을 이미 시작하여 끝내놓을 수 있기 때문이다.

쓰레드 우선순위

쓰레드는 우선순위(Priority)라는 멤버변수를 가지고 있는데, 이 값에 따라 쓰레드가 얻는 실행시간이 달라진다. 쓰레드가 작업의 중요도에 따라 우선순위를 다르게 하여 특정 쓰레드가 더 많은 작업시간을 갖도록 할 수 있다.

void setPriority(int newPriority)	//쓰레드의 우선순위를 지정한 값으로 변경한다.
int getPriority()	//쓰레드의 우선순위를 반환한다.

다음과 같이 쓰레드가 가질 수 있는 우선순위의 범위는 1~10이며 숫자가 높을수록 우선순위가 높다.

public class Test {
    public static void main(String[] args){
        Thread1 t1 = new Thread1();
        Thread2 t2 = new Thread2();

        t2.setPriority(10);

        System.out.println("t1.getPriority() = " + t1.getPriority());
        System.out.println("t2.getPriority() = " + t2.getPriority());

        t1.start();
        t2.start();
    }
}

class Thread1 extends Thread{
    public void run(){
        for(int i=0; i<300; i++){
            System.out.print("ㅡ");
        }
    }
}
class Thread2 extends Thread{
    public void run(){
        for(int i=0; i<300; i++){
            System.out.print("ㅣ");
        }
    }
}
t1.getPriority() = 5
t2.getPriority() = 10
ㅡㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

다음과 같은 코드에서 위의 결과를 얻을 수 있으며 각 우선순위 값도 가져올 수 있다. 위와 같이 싱글 코어로 두개의 쓰레드 작업을 실행했을 때 우선순위가 높은 ㅣ이 먼저 끝난것을 볼수 있다. 하지만 멀티코어에서는 쓰레드의 우선순위에 따른 차이가 거의 없다는 것을 기억하자. 이 이유는 OS마다 다른 방식으로 스케쥴링하기 때문에, 어떤 OS에서 실행하느냐에 따라 다른 결과를 얻을 수 있다. 라는 정도만 알고 넘어가자.

쓰레드 그룹

쓰레드 그룹은 서로 관련된 쓰레드를 그룹으로 다루기 위한 것으로 보안상 이유로 도입된 개념이다. 자신이 속한 쓰레드 그룹이나 하위 쓰레드 그룹은 변경할 수 있지만 다른 쓰레드 그룹의 쓰레드를 변경할수 없다. java 어플리케이션이 실행되면, JVM은 main과 system이라는 쓰레드 그룹을 만들고 JVM 운영에 필요한 쓰레드들을 생성해서 이 쓰레드 그룹에 포함시킨다., main 메서드를 수행하는 main이라는 이름의 쓰레드는 main 쓰레드 그룹에 속하고, 가비지 컬렉션을 수행하는 Finalizer 쓰레드는 system 쓰레드에 속한다.

ThreadGroup getThreadGroup()	//자신이 속한 쓰레드 그룹을 반환한다.

또한 쓰레드 그룹은 쓰레드를 생성할때 지정할 수 있으며 지정하지 않고 생성한다면 main 쓰레드 그룹으로 속하게 된다.

Thread th1 = new Thread(ThreadGroup group, String name);
Thread th1 = new Thread(ThreadGroup group, Runable target, String name);
Thread th1 = new Thread(ThreadGroup group, Runable target, String name, long staticSize);

와 같이 생성할 수 있고 콘솔로 찍어 봤을 때 쓰레드 그룹에 포함된 하위 쓰레드 그룹이나 쓰레드는 들여쓰기를 이용하여 구별되도록 하였다.

데몬 쓰레드

데몬 쓰레드는 다른 일반 쓰레드(데몬 쓰레드가 아닌 쓰레드)의 작업을 보조하는 역할의 쓰레드이다. 일반 쓰레드가 모두 종료되면 데몬 쓰레드는 강제적으로 자동 종료된다. 데몬 쓰레드의 예로는 가비지 컬렉터, 워드프로세서의 자동저장, 화면 자동 갱신 등이 있다.

데몬쓰레드는 무한루프와 조건문을 이용해서 특정 조건이 만족되면 작업을 수행하고 다시 대기하도록 작성한다. 데몬 쓰레드는 일반 쓰레드의 작성방법과 실행방법이 같으며 다만 쓰레드를 생성한 다음 실행하기 전 setDeamon(true)를 호출하여아한다.

boolean isDeamon()	//쓰레드가 데몬 쓰레드인지 아닌지 반환 true면 데몬 쓰레드
void setDeamon(boolean on)	//쓰레드를 데몬 쓰레드로 또는 일반 쓰레드로 변경 true면 데몬, false면 일반

데몬 쓰레드를 사용하여 자동 저장 프로그램을 작성해보자.

public class Test implements Runnable{
    static boolean autoSave = false;
    public static void main(String[] args){
        Thread t1 = new Thread(new Test());
        t1.setDaemon(true);
        t1.start();
        
        for (int i=1; i<=10; 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){}
            if (autoSave){  //true면 저장
                autoSave();
            }
        }
    }
    public void autoSave(){
        System.out.println("자동 저장되었습니다.");
    }
}
1
2
3
4
5
자동 저장되었습니다.
6
7
8
자동 저장되었습니다.
9
10
프로그램 종료

위 코드를 실행하여 5 이후로 자동저장 시스템을 3초마다 저장하도록 작성한 결과를 확인할 수 있다.

profile
코딩을 깔끔하게 하고 싶어하는 초보 개발자 (편하게 글을 쓰기위해 반말체를 사용하고 있습니다! 양해 부탁드려요!) 현재 KakaoVX 근무중입니다!

0개의 댓글