mojo's Blog
wait(), notify(), notifyAll() 을 이용하여 스레드를 동기화하기 본문
wait(), notify(), notifyAll()를 이용하면 producer-consumer 문제의 스레드 동기화를 해결할 수 있다.
java.lang.Object 클래스는 스레드 사이에 동기화를 위한 3개의 메소드 wait(), notify(), notifyAll() 를 제공한다.
모든 객체는 Object 클래스를 상속받기 때문에, 자바는 모든 객체가 동기화 객체가 될 수 있도록 설계하였다.
wait() : 다른 스레드가 이 객체의 notify()를 불러줄 때까지 대기한다.
notify() : 이 객체에 대기 중인 스레드를 깨워 RUNNABLE 상태로 만든다. 2개 이상의 스레드가 대기 중이라도 오직 한 개의 스레드만 깨워 RUNNABLE 상태로 한다.
notifyAll() : 이 객체에 대기 중인 모든 스레드를 깨우고 모두 RUNNABLE 상태로 만든다.
wait(), notify() 를 이용해서 바를 채우는 code
import javax.swing.*; // JFrame
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*; // Container
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.util.Vector;
import java.awt.*;
public class TabAndThreadEx extends JFrame{
private MyLabel bar = new MyLabel(100);
class MyLabel extends JLabel{
private int barSize = 0;
private int maxBarSize;
MyLabel(int maxBarSize){
this.maxBarSize=maxBarSize;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.MAGENTA);
int width = (int)(((double)(this.getWidth()))/maxBarSize*barSize);
if(width==0) return;
g.fillRect(0, 0, width, getHeight());
}
synchronized public void fill() {
if(barSize==maxBarSize) {
try {
wait();
} catch(InterruptedException e) { return; }
}
barSize++;
repaint();
notify(); // ConsumerThread 스레드 깨우기
}
synchronized public void consume() {
if(barSize==0) {
try {
wait();
} catch(InterruptedException e) { return; }
}
barSize--;
repaint();
notify();
}
}
class ConsumerThread extends Thread{
private MyLabel bar;
public ConsumerThread(MyLabel bar) {
this.bar = bar;
}
public void run() {
while(true) {
try {
sleep(200);
bar.consume();
} catch(InterruptedException e) { return; }
}
}
}
TabAndThreadEx(String title){
super(title);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = getContentPane();
c.setLayout(null);
bar.setBackground(Color.ORANGE);
bar.setOpaque(true);
bar.setLocation(20,50);
bar.setSize(300,20);
c.add(bar);
c.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
bar.fill();
}
});
setSize(350, 200);
setVisible(true);
c.setFocusable(true);
c.requestFocus();
ConsumerThread th = new ConsumerThread(bar);
th.start();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new TabAndThreadEx("아무거나 빨리 눌러 바 채우기");
}
}
'Java' 카테고리의 다른 글
명품 JAVA Programming 제 13장 실습문제 (0) | 2021.08.09 |
---|---|
명품 JAVA Programming 제 13장 Open Challenge (0) | 2021.08.09 |
Thread Synchronization (0) | 2021.08.09 |
스레드 정보 출력 / 타이머 스레드 강제 종료 / flag를 이용한 스레드 종료 (0) | 2021.08.09 |
스레드 만들어보기 (0) | 2021.08.08 |
Comments