메인 쓰레드가 종료되면 실행 중인 쓰레드가 있어도 작업을 종료시켜 버린다 하지만 join()을 사용하면
정해진 시간 동안 지정한 쓰레드가 작업하는 것을 기다렸다가 종료한다.
Thread thread = new Thread(task, "thread");
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
public class Main {
public static void main(String[] args) {
Runnable task = () -> {
try {
Thread.sleep(5000); // 5초
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Thread thread = new Thread(task, "thread");
thread.start();
long start = System.currentTimeMillis();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("소요시간 = " + (System.currentTimeMillis() - start));
}
}
메인 쓰레드가 종료되면 모든 쓰레드를 하는데 join()으로 인해 thread의 소요시간인 5초 동안 main 메인 쓰레드가 기다렸다가 종료됩니다.
실행 중인 쓰레드가 interrupt되면 나은 자원을 다음 쓰레드에게 양보하고 자신은 실행 대기 상태가 된다.
Runnable task = () -> {
try {
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName());
}
} catch (InterruptedException e) {
Thread.yield();
}
};
public class Main {
public static void main(String[] args) {
Runnable task = () -> {
try {
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName());
}
} catch (InterruptedException e) {
Thread.yield();
}
};
Thread thread1 = new Thread(task, "thread1");
Thread thread2 = new Thread(task, "thread2");
thread1.start();
thread2.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.interrupt();
}
}
thread1과 2가 1초에 한 번씩 출력되다가 5초뒤에 thread1에서 interruptedException이 발생하면서 Thread.yield();를 호출한다 thread1은 실행 대기 상태로 변경되고서 남은 자원은 thread2에게 양보한다.
멀티 쓰레드의 경우 여러 쓰레드가 한 프로세스의 자원을 공유하는데 이 때문에 서로에게 영향을 줄 수 있다. 이를 방지하기 위해 한 쓰레드가 진행 중인 작업을 다른 쓰레드가 들어오지 못하도록 막는 것을 Synchronization (동기화) 라고 한다.
public synchronized void asyncSum() {
...침범을 막아야하는 코드...
}
synchronized(해당 객체의 참조변수) {
...침범을 막아야하는 코드...
}
public class Main {
public static void main(String[] args) {
AppleStore appleStore = new AppleStore();
Runnable task = () -> {
while (appleStore.getStoredApple() > 0) {
appleStore.eatApple();
System.out.println("남은 사과의 수 = " + appleStore.getStoredApple());
}
};
for (int i = 0; i < 3; i++) {
new Thread(task).start();
}
}
}
class AppleStore {
private int storedApple = 10;
public int getStoredApple() {
return storedApple;
}
public void eatApple() {
if (storedApple > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
storedApple -= 1;
}
}
}
남아 있는 수에 마이너스가 출력되는 모습을 볼 수 있다.
public class Main {
public static void main(String[] args) {
AppleStore appleStore = new AppleStore();
Runnable task = () -> {
while (appleStore.getStoredApple() > 0) {
appleStore.eatApple();
System.out.println("남은 사과의 수 = " + appleStore.getStoredApple());
}
};
for (int i = 0; i < 3; i++) {
new Thread(task).start();
}
}
}
class AppleStore {
private int storedApple = 10;
public int getStoredApple() {
return storedApple;
}
public void eatApple() {
synchronized (this) {
if(storedApple > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
storedApple -= 1;
}
}
}
}
정상적인 숫자가 출력된다.