Thread_wait, notify, notifyAll 사용 방법

7434 단어 notifyAll
wait (), notify (), notify All () 는 Object 클래스에 정의된 세 가지 방법으로 라인의 상태를 제어할 수 있습니다.
이 세 가지 방법은 최종적으로 jvm급의native 방법을 사용한다.jvm 운영 플랫폼에 따라 약간의 차이가 있을 수 있습니다.대상이wait 방법을 사용하면 대상의 라인을 가지고 있는 라인이 대상의 제어권을 넘겨주고 대기 상태가 됩니다.대상이 notify 방법을 사용하면 이 대상의 제어권을 기다리고 있는 라인이 계속 실행될 수 있음을 알립니다.대상이 notifyAll 방법을 호출하면 이 대상의 제어권을 기다리는 모든 라인이 계속 실행될 것을 알립니다.
그 중에서wait방법은 세 가지overload방법이 있는데 그것이 바로wait()wait(long)wait(long,int)이다.
wait 방법은 매개 변수를 통해 기다리는 시간을 지정할 수 있습니다.매개 변수를 지정하지 않으면 기본적으로 알림을 받을 때까지 기다립니다.
다음은 복잡한 문제를 가장 간결하게 설명하는 프레젠테이션 코드입니다.
1. Notify Thread는 3초 후에 다른 대기 상태를 알리는 루틴을 모의하는 루틴 종류이다.
2. WaitThread는 기다리는 라인 종류를 모의하는 데 사용된다.
3. 기다림의 중간 대상은 flag, 하나의 String 대상이다.
main 방법에서 Notify 스레드와 세 개의wait 스레드를 동시에 시작합니다.
 
public class NotifyTest {
		private  String flag = "true";
		
		class NotifyThread extends Thread{   
			public NotifyThread(String name) {   
				super(name);
			}
			
			public void run() {        
				try {
					sleep(3000);//  3       
				} catch (InterruptedException e) {   
					e.printStackTrace();   
				}   
				
				flag = "false";   
				flag.notify();   
			}   
		};   

		class WaitThread extends Thread {   
			public WaitThread(String name) {   
				super(name);   
			}   

			public void run() {   
				while (flag!="false") {   
					System.out.println(getName() + " begin waiting!");   
					long waitTime = System.currentTimeMillis();   
					
					try {   
						flag.wait();   
					} catch (InterruptedException e) {   
						e.printStackTrace();   
					}   
					
					waitTime = System.currentTimeMillis() - waitTime;   
					System.out.println("wait time :"+waitTime);   
				}   
				System.out.println(getName() + " end waiting!");   
			}   
		}   

		public static void main(String[] args) throws InterruptedException {   
			System.out.println("Main Thread Run!");   
			NotifyTest test = new NotifyTest();   
			NotifyThread notifyThread =test.new NotifyThread("notify01");   
			WaitThread waitThread01 = test.new WaitThread("waiter01");   
			WaitThread waitThread02 = test.new WaitThread("waiter02");   
			WaitThread waitThread03 = test.new WaitThread("waiter03");   
			notifyThread.start();   
			waitThread01.start();   
			waitThread02.start();   
			waitThread03.start();   
		}   
}

 
OK, 이 프로그램을 가지고 실행하면 전혀 실행되지 않을 거야, what happened?화면이 가득한java.lang.IllegalMonitorStateException. 맞아, 이 프로그램에는 많은 문제가 있어, 우리 하나씩 보자.우선, 여기서 주의해야 할 몇 가지 사실은 다음과 같다.언제든지 대상의 제어권 (모니터) 은 한 라인에만 있을 수 있습니다.2. 실행 대상의wait, notify, notifyAll 방법이든 현재 실행 중인 라인이 대상의 제어권을 획득했음을 보장해야 한다(monitor).만약 제어권이 없는 라인에서 실행 대상의 상기 세 가지 방법을 실행하면java에 보고할 것이다.lang.Illegal Monitor State Exception 예외.4. JVM은 다중 스레드를 기반으로 하며 기본적으로 런타임 스레드의 시차성을 보장할 수 없습니다.
상기 몇 가지 사실에 근거하여 우리는 라인이 대상의 통제권을 가지도록 확보해야 한다.즉, waitThread에서 wait 방법을 실행할 때 waitThread가 flag에 대한 통제권을 확보해야 한다.notify Thread에서 notify 방법을 실행할 때, notify Thread가 flag에 대한 제어권을 확보해야 합니다.
라인이 통제권을 얻는 방법은 세 가지가 있다.실행 대상의 동기화 실례 방법2. 대상이 대응하는 클래스의 동기화 정적 방법을 실행한다.3. 객체에 동기화 잠금을 설정한 동기화 블록을 실행합니다.
우리는 세 번째 방법으로 설명한다. 상기 notify와wait 방법을 동기화 블록에 포함시킨다
 
synchronized (flag) {   
	flag = "false";   
	flag.notify();   
}  

synchronized (flag) {   
	while (flag!="false") {   
		System.out.println(getName() + " begin waiting!");   
		long waitTime = System.currentTimeMillis();   
	
		try {   
			flag.wait();   
		} catch (InterruptedException e) {   
			e.printStackTrace();   
		}   

		waitTime = System.currentTimeMillis() - waitTime;   
		System.out.println("wait time :"+waitTime);   
	}   
	System.out.println(getName() + " end waiting!");   
}  

 
우리는 한 걸음 앞으로 나아갔다.문제가 해결되었습니까?실행 중인지 자바를 잘못 보고한 것 같습니다.lang.IllegalMonitorStateException.what happened?
이 때의 이상은 flag 대상에 대한 동기화 블록에서 flag 대상의 상태를 변경했기 때문입니다.flag="false"flag.notify();
 
동기화 블록에서 flag에 값을 부여하는 작업을 진행하여 flag가 인용하는 대상을 바꾸었습니다. 이때 notify 방법을 다시 호출할 때 제어권이 없기 때문에 이상을 던집니다.flag을 자바빈으로 바꾸고 속성을 변경하면 flag의 인용에 영향을 주지 않습니다.우리가 이곳에서 수조로 바꾸어 시험해 봐도 같은 효과에 도달할 수 있다.
 
private   String flag[] = {"true"}; 

synchronized (flag) {   
    flag[0] = "false";   
    flag.notify();   
}

synchronized (flag) {
	flag[0] = "false";   
	flag.notify();   
}

synchronized (flag) { 
	while (flag[0]!="false") {   
	System.out.println(getName() + " begin waiting!");   
	long waitTime = System.currentTimeMillis();   

	try {
		flag.wait();   
	} catch (InterruptedException e) {   
		e.printStackTrace();   
	}
}

 
이때 다시 운행하고 이상 보고를 하지 않지만 라인이 끝나지 않았죠. 맞아요. 그리고 라인이 막혀wait상태에 있어요.이유는 매우 간단합니다. 우리는 세 개의wait라인이 있습니다. 단지 하나의 notify라인만 있습니다. notify라인이 notify방법을 실행할 때, 기다리고 있는 라인을 무작위로 알립니다. 그래서 현재는 두 개의 라인이waiting에 있을 것입니다.Notify Thread 스레드 클래스의 flag만 추가하면 됩니다.notify () 방법을 notify All () 로 바꾸면 됩니다.notifyAll 메서드는 객체 제어권을 기다리는 모든 스레드를 알려줍니다.최종 완성판은 다음과 같습니다.
 
public class NotifyTest {
	private String flag[] = { "true" };

	class NotifyThread extends Thread {
		public NotifyThread(String name) {
			super(name);
		}

		public void run() {
			try {
				sleep(3000);//   3    
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			synchronized (flag) {
				flag[0] = "false";
				flag.notifyAll();
			}
		}
	};

	class WaitThread extends Thread {
		public WaitThread(String name) {
			super(name);
		}

		public void run() {
			synchronized (flag) {
				while (flag[0] != "false") {
					System.out.println(getName() + " begin waiting!");
					long waitTime = System.currentTimeMillis();

					try {
						flag.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

					waitTime = System.currentTimeMillis() - waitTime;
					System.out.println("wait time :" + waitTime);
				}
				System.out.println(getName() + " end waiting!");
			}
		}
	}

	public static void main(String[] args) throws InterruptedException {
		System.out.println("Main Thread Run!");
		NotifyTest test = new NotifyTest();
		NotifyThread notifyThread = test.new NotifyThread("notify01");
		WaitThread waitThread01 = test.new WaitThread("waiter01");
		WaitThread waitThread02 = test.new WaitThread("waiter02");
		WaitThread waitThread03 = test.new WaitThread("waiter03");
		notifyThread.start();
		waitThread01.start();
		waitThread02.start();
		waitThread03.start();
	}
}

 
 

좋은 웹페이지 즐겨찾기