JAVA/Java2021-3

동기화 프로그래밍 (wait(), notify()->notifyAll() 사용 추천)

RoarinGom 2021. 10. 29. 18:13

여러개의 resource 중 가능한 상태가 될 때 깨우기!!

 

ex) 책을 빌리는 경우(책은 한정, 사람은 많다)

- notify() 

책 7권 사람 5명 오류 안생김

package Basic_Grammar.chap6.ch16멀티스레드동기화2;

import java.util.ArrayList;

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

    public PublicLibrary() {
        shelf.add("태백산맥1");
        shelf.add("태백산맥2");
        shelf.add("태백산맥3");
        shelf.add("태백산맥4");
        shelf.add("태백산맥5");
        shelf.add("태백산맥6");
        shelf.add("태백산맥7");
    }
    public String lendBook(){
        Thread t=Thread.currentThread(); //메서드를 실행하고 있는 쓰레드 정보를 받을 수 있다.
        String book=shelf.remove(0);
        System.out.println(t.getName()+":"+book+" lend");
        return book;
    }

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

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

//스레드는 책을 빌리는 학생
class Student extends Thread{
    public Student(String name){
        super(name);
    }
    public void run(){

        try {
            //책을 빌려서 5초 후 책을 반납하는 로직
            String title=LibraryMain.library.lendBook();
            if(title==null)return;
            sleep(5000);
            LibraryMain.library.returnBook(title);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
    }
public class LibraryMain {
    public static PublicLibrary library=new PublicLibrary();
    public static void main(String[] args) {
        Student stu1=new Student("stu1");
        Student stu2=new Student("stu2");
        Student stu3=new Student("stu3");
        Student stu4=new Student("stu4");
        Student stu5=new Student("stu5");
        
        stu1.start();
        stu2.start();
        stu3.start();
        stu4.start();
        stu5.start();
        
    }
}

-책 3권 사람 5명 오류 생김 : 책이 없는데 빌릴려고 했기 때문에 예외 발생 (자원이 없어서 기다려야하기 때문에 notify 사용할 것이다.)

package Basic_Grammar.chap6.ch16멀티스레드동기화2;

import java.util.ArrayList;

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

    public PublicLibrary() {
        shelf.add("태백산맥1");
        shelf.add("태백산맥2");
        shelf.add("태백산맥3");
  
    }
    public String lendBook(){
        Thread t=Thread.currentThread(); //메서드를 실행하고 있는 쓰레드 정보를 받을 수 있다.
        String book=shelf.remove(0);
        System.out.println(t.getName()+":"+book+" lend");
        return book;
    }

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

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

//스레드는 책을 빌리는 학생
class Student extends Thread{
    public Student(String name){
        super(name);
    }
    public void run(){

        try {
            //책을 빌려서 5초 후 책을 반납하는 로직
            String title=LibraryMain.library.lendBook();
            if(title==null)return;
            sleep(5000);
            LibraryMain.library.returnBook(title);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
    }
public class LibraryMain {
    public static PublicLibrary library=new PublicLibrary();
    public static void main(String[] args) {
        Student stu1=new Student("stu1");
        Student stu2=new Student("stu2");
        Student stu3=new Student("stu3");
        Student stu4=new Student("stu4");
        Student stu5=new Student("stu5");

        stu1.start();
        stu2.start();
        stu3.start();
        stu4.start();
        stu5.start();

    }
}

-notify() 사용할 것이다.(책 자원이 생기면 빌릴 수 있도록)

wait(), notify() => 둘다 Object 의 함수이므로 그냥 쓰면된다.

package Basic_Grammar.chap6.ch16멀티스레드동기화2;

import java.util.ArrayList;

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

    public PublicLibrary() {
        shelf.add("태백산맥1");
        shelf.add("태백산맥2");
        shelf.add("태백산맥3");

    }
    public synchronized String lendBook() throws InterruptedException {
        Thread t=Thread.currentThread(); //메서드를 실행하고 있는 쓰레드 정보를 받을 수 있다.
        while(shelf.size()==0){
            System.out.println(t.getName()+"-> wait() start");
            wait();
            System.out.println(t.getName()+"-> wait() end");
        }
        if(shelf.size()>0){
            String book=shelf.remove(0);
            System.out.println(t.getName()+":"+book+" lend");
            return book;
        }
        else return null;
    }

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

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

//스레드는 책을 빌리는 학생
class Student extends Thread{
    public Student(String name){
        super(name);
    }
    public void run(){

        try {
            //책을 빌려서 5초 후 책을 반납하는 로직
            String title=LibraryMain.library.lendBook();
            if(title==null){
                System.out.println(getName()+"이 빌리지 못함");
                return;
            }
            sleep(5000);
            LibraryMain.library.returnBook(title);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
    }
public class LibraryMain {
    public static PublicLibrary library=new PublicLibrary();
    public static void main(String[] args) {
        Student stu1=new Student("stu1");
        Student stu2=new Student("stu2");
        Student stu3=new Student("stu3");
        Student stu4=new Student("stu4");
        Student stu5=new Student("stu5");

        stu1.start();
        stu2.start();
        stu3.start();
        stu4.start();
        stu5.start();

    }
}