wait notify 동기 화 zz
synchronized(this){}등가 와 public synchronized void method(){.....}
동기 화 는 클래스 등급 과 대상 등급 으로 나 뉘 는데 각각 클래스 자물쇠 와 대상 자물쇠 에 대응 합 니 다.클래스 잠 금 은 각 클래스 에 하나만 있 습 니 다.static 방법 이 synchronized 키워드 로 수식 되면 이 방법 이 실행 되 기 전에 클래스 잠 금 을 가 져 와 야 합 니 다.대상 잠 금 유사.
우선,Object 의 wait 와 notify/notify All 을 호출 할 때 호출 코드 가 이 Object 에 동기 화 되 어야 합 니 다.즉,synchronized(obj){...}의 내부 에서 만 obj 의 wait 와 notify/notify All 세 가지 방법 을 호출 할 수 있 습 니 다.그렇지 않 으 면 오류 가 발생 합 니 다.
java.lang.IllegalMonitorStateException: current thread not owner
wait 를 호출 할 때 스 레 드 는 자동 으로 소유 한 대상 자 물 쇠 를 풀 고 대상 자 물 쇠 를 신청 하지 않 습 니 다.스 레 드 가 깨 어 났 을 때,그것 은 다시 대상 의 자 물 쇠 를 얻 을 권 리 를 얻 었 다.
따라서 notify 는 notify All 과 크게 다 르 지 않 습 니 다.notify 는 하나의 스 레 드 만 깨 우 고 자 물 쇠 를 얻 을 수 있 도록 합 니 다.notify All 은 이 대상 을 기다 리 는 모든 스 레 드 를 깨 우 고 대상 자 물 쇠 를 얻 을 수 있 도록 합 니 다.synchronied 블록 에 있 는 코드 라면 대상 자 물 쇠 는 한 걸음 도 움 직 일 수 없습니다.사실 하나의 스 레 드 를 깨 우 는 것 은 이 스 레 드 가 대상 의 자 물 쇠 를 얻 고 아래로 실행 하도록 다시 허용 하 는 것 이다.
참고 로 notifyall 은 모든 wait 의 대상 에 게 notify 를 한 번 호출 하지만 이것 은 순서 가 있 습 니 다.모든 대상 이 이 대기 대상 체인 을 저장 하고 호출 하 는 순 서 는 이 체인 의 순서 입 니 다.사실 대기 대상 체인 의 각 스 레 드 를 시작 하 는 것 도 하나의 스 레 드 입 니 다.구체 적 으로 응용 할 때 주의해 야 합 니 다.
class ThreadA
{
public static void main(String[] args)
{
ThreadB b=new ThreadB();
b.start();
System.out.println("b is start....");
synchronized(b)/괄호 안의 b 는 무슨 뜻 입 니까?어떤 역할 을 합 니까?
{
try
{
System.out.println("Waiting for b to complete...");
b.wait();//이 한 마디 가 무슨 뜻 이 야,도대체 누 구 를 기다 리 게 하 는 거 야?
System.out.println("Completed.Now back to main thread");
}catch (InterruptedException e){}
}
System.out.println("Total is :"+b.total);
}
}
class ThreadB extends Thread
{
int total;
public void run()
{
synchronized(this)
{
System.out.println("ThreadB is running..");
for (int i=0;i<100;i++ )
{
total +=i;
System.out.println("total is "+total);
}
notify();
}
}
}
이 프로그램 을 분석 하려 면 먼저 notify()와 wait()를 이해 해 야 한다.왜 며칠 전에 스 레 드 를 기록 할 때 이 두 가지 방법 을 기록 하지 않 았 을 까?이 두 가지 방법 은 원래 Thread 류 가 아니 라 최 하층 object 기초 류 에 속 하기 때문이다.즉,Thread 뿐만 아니 라 모든 대상 에 notify 와 wait 기능 이 있 기 때문이다.왜?그들 은 자 물 쇠 를 조종 하 는 데 사용 되 기 때문에 모든 대상 에 게 자물쇠 가 있 고 자 물 쇠 는 모든 대상 의 기초 이다.자물쇠 가 기본 적 인 것 이 라면 자 물 쇠 를 조종 하 는 방법 도 당연히 가장 기본 적 인 것 이다.
아래 를 내 려 다 보기 전에 먼저 Think in Java 의 14.3.1 중 세 번 째 부분 을 복습 하 는 것 이 좋 습 니 다.기다 림 과 알림,즉 wait()와 notify 입 니 다.
Think in Java 의 설명 에 따 르 면"wait()는 스 레 드 를"수면"상태 에 넣 는 동시에"적 극 적"으로 조건 이 바 뀌 기 를 기다 릴 수 있 습 니 다.또한 하나의 notify()나 notify All()이 바 뀌 었 을 때 만 스 레 드 가 깨 어 나 고 항목 이 바 뀌 었 는 지 확인 할 수 있 습 니 다."
우리 이 말 을 설명해 봅 시다.
"wait()는 스 레 드 를"수면"상태 로 설정 할 수 있 습 니 다.즉,wait 도 현재 스 레 드 를 막 는 것 입 니 다.이 점 은 sleep 또는 suspend 와 같 습 니 다.sleep,suspend 와 어떤 차이 가 있 습 니까?
차이 점 은'(wait)과'적 극 적'으로 조건 이 바 뀌 기 를 기다 리 는 것'이다.이 점 이 관건 이다.sleep 와 suspend 는 할 수 없다.동기 화(synchronized)의 도움 을 통 해 스 레 드 간 의 충돌 을 방지 해 야 할 때 가 있 기 때문이다.동기 화 를 사용 하면 대상 자 물 쇠 를 잠 그 는 것 이다.이 대상 자 물 쇠 를 사용 해 야 하 는 다른 스 레 드 는 줄 을 서서 기다 릴 수 밖 에 없다.동기 화 방법 이나 동기 화 블록 에 있 는 프로그램 이 모두 실 행 될 때 까지 기 회 를 가 질 수 있 습 니 다.동기 화 방법 과 동기 화 블록 에 서 는 sleep()이 든 suspend()든 자신 이 호출 될 수 없 을 때 잠 금 을 해제 합 니 다.그들 은 사용 하고 있 는 대상 의 잠 금 을 강점 하고 있 습 니 다.
wait 는 동기 화 방법 이나 동기 화 블록 을 대상 자 물 쇠 를 잠시 포기 하고 대상 자 물 쇠 를 필요 로 하 는 다른 사람 에 게 잠시 양보 할 수 있 습 니 다.이것 은 wait()를 실행 하 는 동안 스 레 드 대상 의 다른 동기 화 방법 을 호출 할 수 있 음 을 의미 합 니 다!다른 상황 에 서 는(sleep 아,suspend 아)불가능 합 니 다.
하지만 앞에서 말 한 것 을 주의 하 세 요.대상 자 물 쇠 를 잠시 포기 하고 다른 스 레 드 에 잠시 사용 할 뿐 입 니 다.제 wait 가 있 는 스 레 드 는 이 대상 자 물 쇠 를 되 찾 아야 합 니 다.wait 뭐라고 요?남 이 다 쓸 때 까지 기 다 렸 다가 돌려 주 는 거 야!
좋아,그럼 어떻게 대상 자 물 쇠 를 되 찾 지?
첫 번 째 방법 은 빌려 주 는 시간 을 제한 합 니 다.wait()에 파 라 메 터 를 설정 합 니 다.예 를 들 어 wait(1000)는 밀리초 단위 로 제 가 1 초 만 빌려 주 고 1 초 후에 제 가 자동 으로 회수 하 는 것 을 나타 냅 니 다.
두 번 째 방법 은 빌려 준 사람 에 게 그 가 다 써 서 나 에 게 돌려 주 겠 다 고 알려 달라 고 했다.이때 나 는 곧 회수 할 것 이다.아,만약 내 가 1 시간 후에 회수 할 것 을 설정 했다 면 다른 사람 은 30 분 만 에 끝 났 을 것 이다.그러면 어떻게 하지?믿 어!당연히 다 쓰 면 회수 하지,내 가 얼마나 설치 하 든 상관 없어.
그럼 어떻게 알려 주 시 는 거 예요?모두 가 생각 할 수 있 을 거 라 고 믿 습 니 다.notify(),이것 이 바로 마지막 말 입 니 다."그리고 하나의 notify()나 notify All()이 변화 할 때 만 스 레 드 가 깨 어 납 니 다."
따라서 저 희 는 wait()와 notify()를 동기 화 방법 이나 동기 화 블록 내부 에 넣 을 수 있 습 니 다.그 종류 에서 스 레 드 와 관련 된 처 리 를 준비 하 든 말 든.그리고 실제로 우 리 는 동기 화 방법 이나 동기 화 블록 에서 wait()와 notify()를 호출 할 수 밖 에 없습니다.
이때 우리 가 위의 절 차 를 설명 하 는 것 은 정말 식 은 죽 먹 기다.
synchronized(b){...};동기 블록 을 정의 하고 b 를 자원 자물쇠 로 사용 한 다 는 뜻 이다.b.wait();잠 금 을 임시로 풀 고 현재 스 레 드 를 막 아 같은 잠 금 을 사용 하 는 다른 스 레 드 가 실 행 될 수 있 도록 하 는 것 입 니 다.여기 서 같은 잠 금 을 사용 해 야 하 는 것 은 b 스 레 드 자체 입 니 다.이 스 레 드 는 일정한 곳 에 실 행 된 후에 notify()로 wait 의 스 레 드 를 알 립 니 다.잠 금 이 다 되 었 습 니 다.notify()가 있 는 동기 화 블록 이 실 행 된 후에 wait 가 있 는 스 레 드 는 계속 실 행 될 수 있 습 니 다.
생산자 소비자 모델 의 코드 를 추가 합 니 다.
package TestThread;
class SyncStack { //
private int index = 0; // 0
private char[] buffer = new char[6]; // 6
public synchronized void push(char c) { //
while (index == buffer.length) { // ,
try {
this.wait(); // ,
} catch (InterruptedException e) {
}
}
this.notify(); //
buffer[index] = c; //
index++; //
}
public synchronized char[] pop() { //
while (index == 0) { // ,
try {
this.wait(); //
} catch (InterruptedException e) {
}
}
char[] result = new char[index];
while (index > 0) {
result[index - 1] = buffer[index - 1];
index--;
}
this.notify(); //
return result;
// index--; //
// return buffer[index]; //
}
}
class Producer implements Runnable { //
SyncStack theStack;
//
public Producer(SyncStack s) {
theStack = s;
}
public void run() {
char c;
for (int i = 0; i < 26; i++) {
c = (char) (i + 'A');
theStack.push(c); //
System.out.println("Produced: " + c); //
try {
Thread.sleep((int) 10000);
/* */
} catch (InterruptedException e) {
}
}
}
}
class Consumer implements Runnable { //
SyncStack theStack;
//
public Consumer(SyncStack s) {
theStack = s;
}
public void run() {
char[] c;
for (int i = 0; i < 26; i++) {
c = theStack.pop(); //
for (char c1 : c) {
System.out.println("Consumed: " + c1);
if (c1 == 'Z') {
return;
}
}
//
try {
Thread.sleep((int) 1000);
/* */
} catch (InterruptedException e) {
}
}
}
}
public class SyncTest {
public static void main(String args[]) {
SyncStack stack = new SyncStack();
//
Runnable source = new Producer(stack);
Runnable sink = new Consumer(stack);
Thread t1 = new Thread(source); //
Thread t2 = new Thread(sink); //
t1.start(); //
t2.start(); //
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Exception in thread main java.lang. NoClassDefFoundError 오류 해결 방법즉,/home/hadoop/jarfile) 시스템은 Hello World 패키지 아래의class라는 클래스 파일을 실행하고 있다고 오인하여 시스템의 CLASSPATH 아래 (일반적으로 현재 디렉터리를 포함) Hell...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.