JAVA

[Java] Thread Method : wait(), notify()

lakelight 2022. 7. 31. 17:03
728x90
반응형

[Library class]

class LakeLightLibrary{
    public ArrayList<String> shelf = new ArrayList<>();

    public LakeLightLibrary() {
        shelf.add("Book1");
        shelf.add("Book2");
        shelf.add("Book3");
    }

    public String lendBook(){
        Thread thread = Thread.currentThread();

        String book = shelf.remove(0);
        System.out.println(thread.getName() + ": " + book + " lean");

        return book;
    }

    public void returnBook(String book){
        Thread thread = Thread.currentThread();

        shelf.add(book);
        System.out.println(thread.getName() + ": " + book + " return");
    }
}

 

[Student class] - Thread

class Student extends Thread{
    public Student(String name){
        super(name);
    }
    public void run(){
        try {
            String title = LibraryMain.library.lendBook();
            if(title==null) return;
            sleep(5000);
            LibraryMain.library.returnBook(title);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

 

[Library Main class]

public class LibraryMain {
    public static LakeLightLibrary library = new LakeLightLibrary();
    public static void main(String[] args) {
        Student std1 = new Student("std1");
        Student std2 = new Student("std2");
        Student std3 = new Student("std3");
        Student std4 = new Student("std4");
        Student std5 = new Student("std5");

        std1.start();
        std2.start();
        std3.start();
        std4.start();
        std5.start();
    }
}

 

문제

현재 도서관에는 책이 3권밖에 있지 않습니다. 그런데 5명의 학생이 모두 책에 접근하기 때문에
4번, 5번 학생이 접근 할 리소스가 없기 때문에 오류가 발생했습니다.

 

해결방법

1. Thread가 접근하여 처리하는 로직에 synchronized 키워드 추가해줍니다.

2. 책을 빌리는 메서드에 리소스가 없을 때 예외 처리를 해줍니다.

public synchronized String lendBook(){
    Thread thread = Thread.currentThread();

    //서재에 책이 남아있을 때만 빌려주기
    if(shelf.size() > 0){
        String book = shelf.remove(0);
        System.out.println(thread.getName() + ": " + book + " lean");

        return book;
    } else return null;
}

3. wait() 메서드 사용하기 - 쓰레드에게 기다리라고 명령합니다. non-runnable 상태로 만듭니다.

public synchronized String lendBook() throws InterruptedException {
    Thread thread = Thread.currentThread();
    if(shelf.size() == 0){
        System.out.println(thread.getName() + " waiting start");
        //이 메서드를 수행하고 있는 쓰레드를 wait 즉 non-runnable 상태로 만들어라.
        wait();
        System.out.println(thread.getName() + " waiting end");
    }

    //서재에 책이 남아있을 때만 빌려주기
    if(shelf.size() > 0){
        String book = shelf.remove(0);
        System.out.println(thread.getName() + ": " + book + " lean");

        return book;
    } else return null;
}

4. notify() 메서드 사용하기 - non-runnable 상태의 쓰레드를 하나만 runnable 상태로 변경합니다.

public synchronized void returnBook(String book){
    Thread thread = Thread.currentThread();

    shelf.add(book);
    //책을 반납 받으 후에 기다리고 있는 쓰레드를 runnable 상태로 변경해줍니다.
    notify();
    System.out.println(thread.getName() + ": " + book + " return");
}

 

결과
std1: Book1 lean
std5: Book2 lean
std4: Book3 lean
std3 waiting start
std2 waiting start
std4: Book3 return
std3 waiting end
std3: Book3 lean
std5: Book2 return
std2 waiting end
std2: Book2 lean
std1: Book1 return
std3: Book3 return
std2: Book2 return

Process finished with exit code 0

 

결론

wait() 과 notify()를 이용한 동기화 프로그래밍을 해보았습니다.
동기화를 보장해주기 위한 방법을 하나 더 배울 수 있었습니다.

728x90
반응형

'JAVA' 카테고리의 다른 글

[Java] Proxy Pattern  (0) 2022.07.31
[Java] Adapter Pattern  (0) 2022.07.31
[Java] Thread Synchronization  (0) 2022.07.29
[Java] Thread Method : join()  (0) 2022.07.29
[Java] Priority Thread  (0) 2022.07.29