패캠스프링/part2_java
ch 6.23. wait()/notify() 에서드를 활용한 동기화 프로그래밍
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