💎 Thread Termination - Why and When?
⚾ Thread.interrupt()
package thread.interrupt;
public class example {
public static void main(String[] args) {
Thread thread = new Thread(new BlockingTask());
thread.start();
thread.interrupt();
}
private static class BlockingTask implements Runnable {
@Override
public void run() {
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
System.out.println("블로킹 쓰레드 종료");
}
}
}
}
[상황]
사용자가 아주 큰 숫자를 주면 계산이 끝날 때까지 기다려야한다.
package thread.interrupt;
import java.math.BigInteger;
public class example2 {
public static void main(String[] args) {
Thread thread = new Thread(new LongComputationTask(new BigInteger("20000000"), new BigInteger("10000000000")));
thread.start();
thread.interrupt(); // 인터럽트는 보내졌지만, 이를 처리할 메서도느 로직이 없기 때문
}
private static class LongComputationTask implements Runnable{
private BigInteger base;
private BigInteger power;
public LongComputationTask(BigInteger base, BigInteger power) {
this.base = base;
this.power = power;
}
@Override
public void run() {
System.out.println(base+"^"+power+"="+pow(base, power));
}
private BigInteger pow(BigInteger base, BigInteger power) {
BigInteger result = BigInteger.ONE;
for(BigInteger i=BigInteger.ZERO; i.compareTo(power) != 0; i=i.add(BigInteger.ONE)) {
// 해당 스레드가 외부에서 인터럽트 당했는지 확인하는
if (Thread.currentThread().isInterrupted()) {
System.out.println("계산을 종료해라!");
return BigInteger.ZERO;
}
result = result.multiply(base);
}
return result;
}
}
}
[출력]
계산을 종료해라!
20000000^10000000000=0
💎 Daemon Thread
데몬 쓰레드는 백그라운드에서 실행되는 쓰레드로, 메인쓰레드가 종료되어도, 애플리케이션의 종료를 막지 않는다.
package thread.interrupt;
import java.math.BigInteger;
public class example2 {
public static void main(String[] args) {
Thread thread = new Thread(new LongComputationTask(new BigInteger("20000000"), new BigInteger("10000000000")));
thread.setDaemon(true);
thread.start();
thread.interrupt(); // 인터럽트는 보내졌지만, 이를 처리할 메서도느 로직이 없기 때문
}
private static class LongComputationTask implements Runnable{
private BigInteger base;
private BigInteger power;
public LongComputationTask(BigInteger base, BigInteger power) {
this.base = base;
this.power = power;
}
@Override
public void run() {
System.out.println(base+"^"+power+"="+pow(base, power));
}
private BigInteger pow(BigInteger base, BigInteger power) {
BigInteger result = BigInteger.ONE;
for(BigInteger i=BigInteger.ZERO; i.compareTo(power) != 0; i=i.add(BigInteger.ONE)) {
// 해당 스레드가 외부에서 인터럽트 당했는지 확인하는
if (Thread.currentThread().isInterrupted()) {
System.out.println("계산을 종료해라!");
return BigInteger.ZERO;
}
result = result.multiply(base);
}
return result;
}
}
}
[출력]
계산을 종료해라!
해당 쓰레드를 데몬쓰레드로 설정했기 때문에, 애플리케이션이 바로 종료되는 것을 확인할 수 있다
[내용점검]
💡 해당 애플리케이션을 종료시킬려면, 어떻게 해야할까?
public static void main(String [] args) {
Thread thread = new Thread(new WaitingForUserInput());
thread.setName("InputWaitingThread");
[정답]**thread.setDaemon(true);**
thread.start();
}
private static class WaitingForUserInput implements Runnable {
@Override
public void run() {
try {
while (true) {
char input = (char) System.in.read();
if(input == 'q') {
return;
}
}
} catch (IOException e) {
System.out.println("An exception was caught " + e);
};
}
}
💡 thread.interrupt(); 를 호출했을 때, catch 블록을 빈 상태로 두어서는 안된다. 해당 로직이나 메서드를 완성해야 현재 스레드를 중단할 수 있다.
public static void main(String [] args) {
Thread thread = new Thread(new SleepingThread());
thread.start();
thread.interrupt();
}
private static class SleepingThread implements Runnable {
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
[정답]**return; // 해당 부분을 추가해야줘야, 애플리케이션의
//종료가 가능하다.**
}
}
}
}