Java 스레드 학습 노트 (6):join () 방법

join() 메소드 원형:
  • public final void join() throws InterruptedException
  • public final void join(long) throws InterruptedException
  • public final void join(long, int) throws InterruptedException

  • 방법 설명: 예를 들어 설명하자면 라인 대상 A와 라인 대상 B가 있다고 가정한다.온라인 루틴 A의 한 방법에서 루틴 B는 join() 작업을 수행합니다.프로그램이 B.join() 작업으로 실행될 때 스레드 A는 중단되고 스레드 B는 다음 두 가지 상황이 발생합니다.
    1. join () 방법에 매개 변수가 없으면 스레드 A는 스레드 B가 실행될 때까지 기다린 후에 계속 실행합니다
    2,join() 방법은 매개 변수(join(m)나join(m,n))를 가지고 있으면 대기 시간을 나타낸다.루틴 B가 실행되기 시작하면, 루틴 A는join () 방법에서 지정한 시간을 기다린 후, 루틴 B가 실행되었든 안 되었든 간에 루틴 A가 실행을 회복합니다.
     
    join () 작업의 이상 및 대기 시간 처리
    방정식 소스 코드는 다음과 같습니다.
    public final synchronized void join(long millis)
        throws InterruptedException {
            long base = System.currentTimeMillis();
            long now = 0;
    
            if (millis < 0) {
                throw new IllegalArgumentException("timeout value is negative");
            }
    
            if (millis == 0) {
                while (isAlive()) {
                    wait(0);
                }
            } else {
                while (isAlive()) {
                    long delay = millis - now;
                    if (delay <= 0) {
                        break;
                    }
                    wait(delay);
                    now = System.currentTimeMillis() - base;
                }
            }
        }
    
        public final synchronized void join(long millis, int nanos)
        throws InterruptedException {
    
            // 0 , 
            if (millis < 0) {
                throw new IllegalArgumentException("timeout value is negative");
            }
    
            // 0 999999 , , 
            if (nanos < 0 || nanos > 999999) {
                throw new IllegalArgumentException(
                                    "nanosecond timeout value out of range");
            }
    
            // 500000, 0 0 , 
            if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
                millis++;
            }
    
            // join(loing) 
            join(millis);
        }
    
        public final void join() throws InterruptedException {
            join(0);
        }
    

    예 1:
    class Sleeper extends Thread {
    	private int duration;
    	private double d = 0;
    	
    	public Sleeper(String name, int sleepTime) {
    		super(name);
    		duration = sleepTime;
    		start();
    	}
    	
    	public String toString() {
    		return Thread.currentThread().toString();
    	}
    	
    	public void run() {
    		try {
    			System.out.println(getName() + " start run()");
    			sleep(duration);
    		} catch (InterruptedException e) {
    			System.out.println(getName() + " was interrupted. "
    					+ "isInterrupted(): " + isInterrupted());
    			return;
    		}
    		System.out.println(getName() + " has awakened");
    		// 
    		for (int i = 0; i < 900000; i++) {
    			d += (Math.E + Math.PI) / d;
    		}
    		System.out.println(getName() + " !");
    	}
    }
    
    class Joiner extends Thread {
    	private Sleeper sleeper;
    	public Joiner(String name, Sleeper sleeper) {
    		super(name);
    		this.sleeper = sleeper;
    		start();
    	}
    	
    	public String toString() {
    		return Thread.currentThread().toString();
    	}
    	
    	public void run(){
    		try {
    			System.out.println(getName() + " start run()");
    			sleeper.join();
    		} catch (InterruptedException e) {
    			System.out.println("Interrupted");
    		}
    		System.out.println(getName() + " join completed");
    	}
    }
    
    public class Joining {
    	public static void main(String[] args) {
    		Sleeper
    		sleepy  = new Sleeper("Sleepy", 5000),
    		grumpy = new Sleeper("Grumpy", 5000);
    		
    		Joiner
    		dopey = new Joiner("Dopey", sleepy),
    		doc = new Joiner("Doc", grumpy);
    		
    		System.out.println("sleepy's id is " + sleepy.getId());
    		System.out.println("dopey's id is " + dopey.getId());
    	}
    }

    실행 결과 쓰기
    Sleepy start run()
    Grumpy start run()
    sleepy's id is 8
    dopey's id is 10
    Dopey start run()
    Doc start run()
    Sleepy has awakened
    Grumpy has awakened
    Grumpy 실행 완료!
    Doc join completed
    슬리피 작업 완료!
    Dopey join completed
    분석:
  • 출력 결과 분석에 따라 전기에는 모든 라인이 작동
  • dopey의run()에서sleepy는join() 방법을 호출하고 출력된 id에 따라dopey와sleepy가 같은 라인이 아니라는 것을 알 수 있다
  • join () 방법에는 인자가 없습니다. 인자가 실행될 때dopey는sleepy가 실행될 때까지dopey가 계속 실행됩니다
  • 예2: 예1에서join() 방법을join(500)으로 변경
    실행 결과 쓰기
    sleepy's id is 8
    dopey's id is 10
    Sleepy start run()
    Grumpy start run()
    Dopey start run()
    Doc start run()
    Dopey join completed
    Doc join completed
    Sleepy has awakened
    Grumpy has awakened
    슬리피 작업 완료!
    Grumpy 실행 완료!
    분석:join()에 매개 변수 500을 추가하면dopey는sleepy 500밀리초만 기다리고 이 시간에dopey만 계속 실행되며 sleepy가 실행되는지 안 되는지는 상관하지 않습니다.
     
    join()의 예외, 예:
    class DemoA extends Thread {
    	
    	private double d = 0.0;
    	
    	public DemoA() {
    		start();
    	}
    	
    	public void run() {
    		System.out.println("start DemoA!");
    		while (!this.isInterrupted()) {
    			for (int i = 0; i < 900000; i++) {
    				d = d + (Math.PI + Math.E) / d;
    			}
    			//System.out.println("d = " + d);
    		}
    		System.out.println("end DemoA!");
    	}
    }
    
    class DemoB extends Thread {
    	
    	private Thread demo;
    	
    	public DemoB(Thread demo) {
    		this.demo = demo;
    		start();
    	}
    	
    	public void run() {
    		System.out.println("start DemoB!");
    		try {
    			demo.join();
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.println("end DemoB!");
    	}
    }
    
    public class Hello {
    	public static void main(String[] args) throws InterruptedException {
    		DemoA a = new DemoA();
    		DemoB b = new DemoB(a);
    		
    		Thread.sleep(2000);
    		b.interrupt();
    		
    		Thread.sleep(2000);
    		System.out.println("DemoA intreeupted is " + a.isInterrupted());
    		System.out.println("DemoB intreeupted is " + b.isInterrupted());
    	}
    }

    실행 결과 쓰기
    start DemoA!
    start DemoB!
    end DemoB!
    DemoA intreeupted is false
    DemoB intreeupted is false
    java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Thread.join(Thread.java:1280)
    at java.lang.Thread.join(Thread.java:1354)
    at com.test4.DemoB.run(Hello.java:35)
    분석: DemoB가 중단 작업을 수행할 때join() 방법에 이상이 발생하고 DemoB의 중단 상태가false인 것을 알 수 있다.JavaAPI에 따르면 Join () 방법을 호출하면 현재 라인이 중단되면 java를 던집니다.lang.InterruptedException 예외이며 스레드의 중단 상태가 제거되었습니다.
     
    참고: 본 문서의 코드는 Think in Java(Fourth Edition)에서 21.2.11에 스레드를 추가한 것에서 파생된 것입니다.
    본고는 현재 개인이 이해한 결과로 참고로 제공할 뿐입니다. 만약에 후속으로 문제가 발견되면 저는 해당하는 수정을 할 것입니다. 또한 자바 라인에 관심이 있는 친구나 선배들의 지적을 환영합니다.

    좋은 웹페이지 즐겨찾기