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 |