실습 자료 : https://github.com/helloJosh/nhn-homework-thread-study
자바에서는 synchronized method, block을 제어하기 위해 wait(), notify(), notifyAll()을 지원한다. 네트워크 프로그래밍이 이런 식으로 프로그래밍되어있어 은근 중요한 부분 같다.
wait, notify, notifyAll은 Thread의 static method가 아닌 instance method이다.
public class Data {
private String packet;
private boolean transfer = true;
public synchronized String receive(){
while(transfer){
try{
wait();
//Thread.sleep(1000); 계속 리시버만 돌고 있다.
} catch (InterruptedException e){
Thread.currentThread().interrupt();
}
}
transfer = true;
String returnPacket = packet;
notifyAll();
return returnPacket;
}
public synchronized void send(String packet){
while(!transfer){
try{
wait();
} catch (InterruptedException e){
Thread.currentThread().interrupt();
}
}
transfer = false;
this.packet = packet;
notifyAll();
}
public static void main(String[] args) {
Data data = new Data();
Thread sender = new Thread(new Sender(data));
Thread receiver1 = new Thread(new Receiver(data));
Thread receiver2 = new Thread(new Receiver(data));
sender.start();
receiver1.start();
receiver2.start();
}
}
public class Receiver implements Runnable{
private Data load;
public Receiver(Data load) {
this.load = load;
}
public void run(){
for(String receivedMessage = load.receive(); !"End".equals(receivedMessage);receivedMessage= load.receive()){
System.out.println(receivedMessage);
try{
Thread.sleep(ThreadLocalRandom.current().nextInt(1000,5000));
} catch (InterruptedException e){
Thread.currentThread().interrupt();
System.err.println("Thread Interrupted");
}
}
}
}
public class Sender implements Runnable {
private Data data;
public Sender(Data data) {
this.data = data;
}
public void run(){
String packets[] ={
"1st packet",
"2nd packet",
"3rd packet",
"4th packet",
"End"
};
for(String packet : packets){
data.send(packet);
try{
Thread.sleep(ThreadLocalRandom.current().nextInt(1000,5000));
} catch (InterruptedException e){
Thread.currentThread().interrupt();
System.err.println("Thread Interrupted");
}
}
}
}
참고
- 위에 주석에 있는 것처럼 wait() 과 sleep()은 다르다.
- wait()은 공유 자원에 접근 안한 상태로 대기중인 것이고
- sleep()은 자원을 갖고 있는 상태에서 쉬는 것이다.
- 따라서 wait()을 주석하고 sleep()를 주석을 풀게되면 Receiver만 돌게 된다.