상세 컨텐츠

본문 제목

ch 6.23. wait()/notify() 에서드를 활용한 동기화 프로그래밍

패캠스프링/part2_java

by hippo0207 2022. 7. 18. 18:50

본문

23. wait()/notify() 에서드를 활용한 동기화 프로그래밍

 

Chapter6/6-23 · master · Youngju-Jang / Javacoursework · GitLab

GitLab.com

gitlab.com

resource 는 여러개 & resource가 부족한경우  >> wait상태로 뒀다가 >>사용가능한 상태가 될때 깨움
(방법 2가지 notify,notifyAll)

뭐가 먼저 깨어날지 모름  > nofity : 영원히 안깨는게 있을ㅇ수 있음

  • notify()가 호출되고 wait() 하고 있는 Thread 중 무작위로 하나의 Thread를 재시작 하도록 한다.
  • notifyAll()이 호출되는 경우 wait() 하고 있는 모든 Thread가 재시작 된다. & 모두가 경쟁상태로 됨
  • 이 경우 유효한 리소스만큼의 Thread만이 수행될 수 있고 자원을 갖지 못한 Thread의 경우는 다시 wait() 상태로 만든다.
  • 자바에서는 notifyAll() 메서드의 사용을 권장한다.
  • 도서관에서 책을 빌리는 예제
    • 1. 계속 대기하며 책있냐 묻기 (resource 폴링?)
    • 2. 연락처 남기고 알림받기 ( 1명에게 알람: notify, 모두에게 알람 : notifyAll)
    • 한명이 빌리고 5초후 반납하기임 
package ch6;

import java.util.ArrayList;

class FastLibrary{
	
	public ArrayList<String> shelf = new ArrayList<String>();
	
	public FastLibrary() {
		shelf.add("태백산맥 1");
		shelf.add("태백산맥 2");
		shelf.add("태백산맥 3");
	}
	
	public synchronized String lendBook() {
		
		Thread t = Thread.currentThread();
		
		/*
        String book = shelf.remove(0);
		System.out.println(t.getName() + " : " + book + " lend");
		
		return book;
        */        
        if(shelf.size() == 0) {
			System.out.println(t.getName() + " waiting start");
			wait(); 
            // object method >> Thread.wait()안하고 걍 wait()하면됨
			// 이 메서드를 사용하고있는 스레드가 unrunnable됨
			System.out.println(t.getName() + " waiting 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 {
			String title = LibraryMain.library.lendBook();
			if( title == null) {
				System.out.println(getName() + " 못빌렸음");
				return;
			}
			sleep(5000);
			LibraryMain.library.returnBook(title);
			
		} catch (InterruptedException e) {
			System.out.println(e);
		}
		
	
	}
}


public class LibraryMain {

	public static FastLibrary library = new FastLibrary();
	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");
        Student std6 = new Student("std5");
		
		std1.start();
		std2.start();
		std3.start();
		std4.start();
		std5.start();
        std6.start();
	}

}
=======맨 기본상태=====
std3 : 태백산맥 3 lend
std2 : 태백산맥 2 lend
std4 : 태백산맥 4 lend
std1 : 태백산맥 1 lend
std5 : 태백산맥 5 lend
std1 : 태백산맥 1 return
std3 : 태백산맥 3 return
std2 : 태백산맥 2 return
std5 : 태백산맥 5 return
std4 : 태백산맥 4 return   >> 책 수, 학생수가 같으면 별문제없으나,
-----------책3권, 학생 6으로 늘리면 ----------------

Exception in thread "std4" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10
std3 : 태백산맥 3 lend
std1 : 태백산맥 1 lend
std2 : 태백산맥 2 lend
	at java.base/java.util.ArrayList.fastRemove(ArrayList.java:674)
    오류막뜸 자원이없음
    
 ============= sync, wait(), notify() 넣으면 =================
 std1 : 태백산맥 1 lend
std5 : 태백산맥 2 lend
std5 : 태백산맥 3 lend
std4 waiting start
std2 waiting start
std3 waiting start
std5 : 태백산맥 2 return  >>> 깨움
std4 waiting end
std4 : 태백산맥 2 lend 
std5 : 태백산맥 3 return  >>> 깨움
std1 : 태백산맥 1 return  >>> 깨움
std3 waiting end
std3 : 태백산맥 3 lend
std2 waiting end
std2 : 태백산맥 1 lend
std3 : 태백산맥 3 return
std2 : 태백산맥 1 return
std4 : 태백산맥 2 return

notifyAll()을 사용하는 경우

lendBook()/ returnBook() 메서드 수정

public synchronized String lendBook() throws InterruptedException{
		
		Thread t = Thread.currentThread();
		
		while( shelf.size() == 0 ){   >> while로 바뀌고 
			System.out.println(t.getName() + " waiting start");
			wait();
			System.out.println(t.getName() + " waiting end");
		}  >>> 빌리지못하는경우는 없으므로 shelf.size() != 0 인경우를 없앰
		String book = shelf.remove(0);
		System.out.println(t.getName() + ": " + book + " lend");
		
		return book;
	}
}

public synchronized void returnBook(String book){

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

--------------------------
std1 : 태백산맥 1 lend
std5 : 태백산맥 2 lend
std5 : 태백산맥 3 lend
std4 waiting start
std3 waiting start
std2 waiting start
std1 : 태백산맥 1 return
std4 waiting end
std4 : 태백산맥 1 lend
std5 : 태백산맥 2 return
std2 waiting end
std2 : 태백산맥 2 lend
std3 waiting end 
std3 waiting start   >> 깼다가 자원없어서 다시잠듦
std5 : 태백산맥 3 return
std3 waiting end
std3 : 태백산맥 3 lend
std2 : 태백산맥 2 return
std4 : 태백산맥 1 return
std3 : 태백산맥 3 return

 

'패캠스프링 > part2_java' 카테고리의 다른 글

ch8 알고리즘  (0) 2022.07.19
ch7~ 학점 산출 프로그램  (0) 2022.07.19
ch 6.22 멀티 Thread 프로그래밍에서의 동기화  (0) 2022.07.18
ch 6.21~ thread 메소드들  (0) 2022.07.18
ch6.20~22 thread 스레드  (0) 2022.07.15

관련글 더보기

댓글 영역