[Java] 쓰레드 생성 방법 Thread & Runnable Interface
✨Goal
1. Thread Class를 상속받아 스레드를 생성하는 방법에 대해 숙지한다.
2. Runnable Interface를 구현하여 스레드를 생성하는 방법에 대해 숙지한다.
자바에서 스레드를 생성하는 방법은 Thread 클래스를 상속받는 방식과 Runnable 인터페이스를 구현하는 방식으로 나뉜다.
#1 extends Thread
Thread 클래스를 상속받아 스레드를 생성한다.
* Thread.currentThread().getName() - 현재 실행중인 스레드의 이름을 반환한다.
run() 메서드 내부에 스레드가 수행할 동작을 명시하며 외부에서 start() 메서드를 호출하면 스레드 내부의 run() 메서드가 호출된다.
public class MyThread extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ": run()");
}
}
public class MyThreadMain {
public static void main(String[] args) {
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread1.start(); // myThread1.run()
myThread2.start(); // myThread2.run()
}
}
스레드의 실행순서는 운영체제의 스케줄링 방식에 따라 결정되어 매 번 달라지기에 보장되지 않는다.
별도의 스레드 명을 설정해 주지 않을 경우 아래 콘솔 결과와 같이 (Thread-N ...) 임의로 부여된다.
Thread-1: run()
Thread-0: run()
#2 implement Runnable Interface
Runnable Interface를 구현하여 스레드를 생성한다.
Runnable Interface를 구현한 클래스의 인스턴스를 생성한 뒤, 작업을 실행할 스레드로 인스턴스를 전달한다.
즉 Runnable은 스레드가 실행할 작업 명세서이며, Thread는 실제로 명세서에 적힌 작업을 실행하는 주체이다.
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ": run()");
}
}
Thread Constructor의 첫 번째 인자로 Runnable 객체를 두 번째 인자로 문자열을 전달하여 스레드의 이름을 설정해 줄 수 도 있다.
public class HelloRunnableMain {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable(); // 스레드가 실행할 작업
Thread thread = new Thread(runnable, "NovThread"); // 작업을 스레드로 전달, 스레드 이름 설정
thread.start(); // 작업 실행
}
}
NovThread: run()
스레드 이름 설정 방법
• 스레드 생성 시 이름 지정: new Thread(new Runnable(), "ThreadName")
• 스레드 생성 후 이름 변경: thread.setName("NewName")
• 현재 스레드 이름 가져오기: Thread.currentThread().getName()
#3 Thread vs Runnable
Thread 클래스에서 제공하는 기능이 꼭 필요한 상황이 아니라면 Runnable 인터페이스를 구현하는 방식을 권장한다.
Runnable 인터페이스를 구현하는 방식은 Thread의 생성부와 실행부가 분리되어 있기에, 가독성이 높아진다.
또한 JAVA 언어 특성상 Python과 같은 언어와는 달리 다중 상속을 지원하지 않는다.
따라서 Thread 클래스를 상속받으면 다른 클래스를 더 이상 상속받지 못해 코드 유연성이 떨어진다.
public class MyThread extends Thread, AnotherThread // 불가능{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ": run()");
}
}