[Java] 스레드(Thread) - wait(), notify() 활용 예제

2022. 2. 27. 22:25Back-end/Java

  • 리소스가 어떤 조건에서 더 이상 유효하지 않은 경우 리소스를 기다리기 위해 Thread가 wait() 상태가 된다
  • wait() 상태가 된 Thread는 notify()가 호출될 때까지 기다린다
  • 유효한 자원이 생기면 notify()가 호출되고 wait()하고 있는 Thread 중 무작위로 하나의 Thread를 재시작한다
  • notifyAll()이 호출되는 경우 wait() 하고 있는 모든 Thread가 재시작된다
  • notifyAll()이 호출되는 경우 유효한 리소스만큼의 Thread만이 수행되며 자원을 갖지 못한 Thread는 다시 wait() 상태로 돌아간다
  • 자바에서는 notifyAll() 메서드의 사용을 권장한다

 

도서관에 자리가 부족해 기다리는 경우를 가장한 코딩 예제

notify()를 사용하는 경우
import java.util.ArrayList;

class JavaLibrary {

	public ArrayList<String> arrayList = new ArrayList<String>();

	public JavaLibrary() {
		arrayList.add("1번 자리");
		arrayList.add("2번 자리");
		arrayList.add("3번 자리");
	}

	public synchronized String study() throws InterruptedException {

		Thread t = Thread.currentThread();

		if (arrayList.size() == 0) {
			System.out.println(t.getName() + " wait start");
			wait();
			System.out.println(t.getName() + " wait end");
		}
        
		if (arrayList.size() > 0) {
			String seat = arrayList.remove(0);
			System.out.println(t.getName() + " : " + seat);
			return seat;
		} else
			return null;
	}

	public synchronized void returnSeat(String seat) {

		Thread t = Thread.currentThread();

		arrayList.add(seat);
		notify();
		System.out.println(t.getName() + " : " + seat + " return");
	}

}

class Student extends Thread {

	public void run() {

		try {
			String seatNum = LibraryMain.library.study();
			if (seatNum == null)
				return;
			sleep(5000);
			LibraryMain.library.returnSeat(seatNum);

		} catch (InterruptedException e) {
			System.out.println(e);
		}
	}

}

public class LibraryMain {

	public static JavaLibrary library = new JavaLibrary();

	public static void main(String[] args) {

		Student student1 = new Student();
		Student student2 = new Student();
		Student student3 = new Student();
		Student student4 = new Student();
		Student student5 = new Student();
		Student student6 = new Student();

		student1.start();
		student2.start();
		student3.start();
		student4.start();
		student5.start();
		student6.start();
	}

}
[Console]
Thread-0 : 1번 자리
Thread-4 : 2번 자리
Thread-5 : 3번 자리
Thread-3 wait start
Thread-2 wait start
Thread-1 wait start
Thread-0 : 1번 자리 return
Thread-3 wait end
Thread-3 : 1번 자리
Thread-4 : 2번 자리 return
Thread-5 : 3번 자리 return
Thread-1 wait end
Thread-1 : 2번 자리
Thread-2 wait end
Thread-2 : 3번 자리
Thread-2 : 3번 자리 return
Thread-1 : 2번 자리 return
Thread-3 : 1번 자리 return

 

notifyAll()을 사용하는 경우
public synchronized String study() throws InterruptedException {

		Thread t = Thread.currentThread();

		while (arrayList.size() == 0) {
			System.out.println(t.getName() + " wait start");
			wait();
			System.out.println(t.getName() + " wait end");
		}

		if (arrayList.size() > 0) {
			String seat = arrayList.remove(0);
			System.out.println(t.getName() + " : " + seat);
			return seat;
		} else
			return null;
	}

	public synchronized void returnSeat(String seat) {

		Thread t = Thread.currentThread();

		arrayList.add(seat);
		notifyAll();
		System.out.println(t.getName() + " : " + seat + " return");
	}
study 메서드 수정 : if (arrayList.size() == 0) -> while (arrayList.size() == 0)
returnSeat 메서드 수정 : notify() -> notifyAll()
반응형