Runnable
은 파라미터도 없고 리턴 값도 없는 함수형 인터페이스이다. -> run()
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Runnable
을 구현하여 Thread
의 생성자 파라미터로 사용한다.Runnable
인스턴스로 생성한 Thread
들은 병렬적이지 않고 직렬적이다.class MyRunnable implements Runnable{
@Override
public void run() {
String threadName = Thread.currentThread().getName();
String threadGroup = Thread.currentThread().getThreadGroup().getName();
for(int i = 0; i < 5; i++) {
System.out.println("[" + threadGroup + "] " + threadName + ": " + i);
}
}
}
Runnable r1 = new MyRunnable();
Runnable r2 = new MyRunnable();
Runnable r3 = new MyRunnable();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r3);
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.start();
t2.start();
t3.start();
[main] t2: 0
[main] t2: 1
[main] t3: 0
[main] t3: 1
[main] t3: 2
[main] t1: 0
[main] t1: 1
[main] t1: 2
[main] t1: 3
[main] t1: 4
[main] t3: 3
[main] t3: 4
[main] t2: 2
[main] t2: 3
[main] t2: 4
Process finished with exit code 0
Name : Signal Dispatcher(데몬)
소속그룹 : system
Name : AutoSaveThread(데몬)
소속그룹 : main
Name : main(주)
소속그룹 : main
Name : Attach Listener(데몬)
소속그룹 : system
Name : Finalizer(데몬) - 가비지 컬렉터 담당.
소속그룹 : system
Name : Reference Handler(데몬)
소속그룹 : system
main()
함수 호출은 main 스레드 그룹에 속한 main 스레드를 실행하는 것이다. 따라서 main 스레드 그룹에서 시작한다.interrupt()
가 가능하다.Thread
는 Runnable
을 implements 하여 run()
이 존재한다.Thread
를 extends 하고 run()
을 오버라이딩 해도 된다.Thread
는 start()
에 의하여 실행된다.public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
start()
를 하면 해당 스레드를 스레드 그룹에 추가한다.Thread
의 생성자는 다음과 같다.Runnable
, name, ThreadGroup
, stackSize 설정이 가능하다.class MyThread extends Thread{
public MyThread(String name) {
super(name);
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
String threadGroup = Thread.currentThread().getThreadGroup().getName();
for(int i = 0; i < 5; i++) {
System.out.println("[" + threadGroup + "] " + threadName + ": " + i);
}
}
}
Thread t1 = new MyThread("t1");
Thread t2 = new MyThread("t2");
Thread t3 = new MyThread("t3");
t1.start();
t2.start();
t3.start();
[main] t3: 0
[main] t3: 1
[main] t3: 2
[main] t3: 3
[main] t3: 4
[main] t1: 0
[main] t1: 1
[main] t1: 2
[main] t1: 3
[main] t1: 4
[main] t2: 0
[main] t2: 1
[main] t2: 2
[main] t2: 3
[main] t2: 4
Process finished with exit code 0
Runnable
구현하여 생성자를 통해 넘기는 방법처럼 Thread
를 상속 받아서 구현할 수 있다.interrupt()
사용isInterrupted()
아닐 때 까지 넣는다.interrupt()
하면 while문 빠져나오게 된다.stop()
은 안전하지 않아 Deprecated 되어 있음.Thread
상속받는거 보다는 Runnable
을 구현하여 생성자로 넘기는 방법이 좋을 것 같다.교착상태(Deadlock)란 둘 이상의 스레드가 서로의 작업이 끝나기만을 기다리며 작업을 더 이상 진행하지 못하는 상태를 의미한다.