JAVA

Thread(쓰레드)

🤖 Play with Android 🤖 2021. 7. 15. 11:12
728x90


 

Thread(쓰레드)

 

운영체제(OS)에서 실행 중인 하나의 어플리케이션 즉 ctrl + alt + del창 작업 관리자에서 프로세스 탭에 올라와 있는 어플리케이션 하나를 하나의 프로세스라고 부른다.

 

Thread(쓰레드)는 간단히 정의하면 하나의 프로세스에서 독립접으로 실행되는 하나의 일, 또는 작업의 단위를 말한다.

간단히 말해 쓰레드를 여러개 사용하면 동시에 여러 작업을 할 수 있는 뜻이다.

우리가 익히 알고 있는 main 함수 역시 쓰레드이다. 프로그램 실행 시 실행되는 첫번째 쓰레드이기 때문에 main함수를 우리는 메인 쓰레드라고도 한다.

 

쓰레드의 장점

  • 가장 큰 장점은 동시성, 동시에 여러 일들을 할 수 있다. 그렇기 때문에 작업의 효율성을 높일 수 있게 된다.
  • 쓰레드끼리 메모리를 공유한다. 그렇기 때문에 메모리가 절약되는 효과를 볼 수 있어 경제적이다.

 

쓰레드를 생성하는 방법에는 크게 두가지가 있다

1) Thread 클래스를 상속받는 방법

2) Runnable 인터페이스를 상속받는 방법

 


Thread 클래스를 상속받는 방법

// 쓰레드를 생성하는 두가지 방법 중 Thread 클래스를 상속받는 방법

public class MyThread1 extends Thread {

    String str;

    // 생성할 때 부터 필드를 받아드릴 수 있도록 생성자를 만든다.
    public MyThread1(String str){
        this.str = str;
    }

    @Override
    public void run() {
        for(int i = 0; i < 10; i++){
            System.out.println(str);

            try {
                Thread.sleep((int)Math.random()*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

 

이것을 main 메소드에서 실행시켜보자

 

public class ThreadExam {
    public static void main(String[] args) {
        MyThread1 t1 = new MyThread1("*");
        MyThread1 t2 = new MyThread1("-");

        // 쓰레드가 run메소드를 직접 호출하는게 아니라 start()메소드를 호출해야한다.
        t1.start(); //이때 프로그램의 흐름이 2개로 나뉜다. 메인흐름과 t1의 run 메소드 흐름
        t2.start(); // 흐름이 t2의 run 메소드 흐름까지 3개로 나뉜다

        System.out.println("main end!!!");
        // 메인 쓰레드가 종료가 되어도 다른 쓰레드들이 동작한다.
        // 모든 쓰레드들이 흐름이 종료가 되어야 프로그램이 종료가 된다.
    }
}

MyThread1 클래스가 Thread 클래스를 상속했다. Thread 클래스의 run 메소드를 구현하면 위 예제와 같이 test.start() 실행 시 MyThread1 객체의 run 메소드가 수행이 된다. (Thread 클래스를 extends 했기때문에 start 메소드 실행 시 run 메소드가 수행되는 것이다. Thread 클래스는 start 실행 시 run 메소드가 수행되도록 내부적으로 코딩되어 있다.)

 

 

 

Runnable 인터페이스를 상속받는 방법

// 쓰레드를 생성하는 두가지 방법 중 Runnable 인터페이스를 상속받는 방법
// 자바는 단일상속 즉 하나의 클래스만을 상속받을 수 있기 때문에 만약 다른 클래스를 상속 받고 있을 경우
// Runnable 인터페이스를 사용하여 쓰레드를 사용하면 된다.

public class MyThread2 implements Runnable {
    String str;
    public MyThread2(String str){
        this.str = str;
    }
    // Runnable 인터페이스는 run 이라는 메소드를 가지고 있기 때문에 꼭 run 메소드가 있어야 한다.(인터페이스의 속성)
    @Override
    public void run() {
        for(int i = 0; i < 10; i++){
            System.out.println(str);
            try {
                Thread.sleep((int)Math.random()*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

 

 

이것을 main 메소드에서 실행시켜보자

 

public class ThreadExam2 {
    public static void main(String[] args) {
        MyThread2 t1 = new MyThread2("*");
        MyThread2 t2 = new MyThread2("-");

        // 여기서는 Runnable 인터페이스를 사용했기 때문에 start()라는 메소드가 없다
        // 따라서 새롭게 Thread 객체를 하나 만들어서 start() 메소드를 사용해야 한다.
        Thread thread1 = new Thread(t1);
        Thread thread2 = new Thread(t2);

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

        System.out.println("main end!!!");
    }
}

여기서는 특이하게 새롭게 Thread 객체를 만들어 start() 메소드를 사용했는데 이것은 이번 방법에서는 Runnable 인터페이스를 사용했기 때문에 Thread 클래스를 상속받지 않아서 내장된 start() 메소드가 없기 때문이다.