Java 멀티스레드에서 join, yield, sleep 메소드 자세히 보기

7191 단어
Java 멀티스레드 프로그래밍에서 Thread 클래스는 그 중의 핵심과 관건적인 역할이다.따라서 이 유형의 일부 기초 상용 방법에 대한 이해와 숙련된 사용은 다선정 코드 개발의 기초이다.이 편은 주로 Thread에서 자주 사용하는 정적 방법의 의미와 코드의 사용을 총괄한다.
sleep 방법
소스는 다음과 같습니다.
    /**
     * Causes the currently executing thread to sleep (temporarily cease
     * execution) for the specified number of milliseconds, subject to
     * the precision and accuracy of system timers and schedulers. The thread
     * does not lose ownership of any monitors.
     *
     * @param  millis
     *         the length of time to sleep in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          interrupted status of the current thread is
     *          cleared when this exception is thrown.
     */
    public static native void sleep(long millis) throws InterruptedException;

슬라이드는 정적 로컬 방법인 것을 알 수 있다. 로컬 방법이기 때문에 자바 코드의 실현이 없고 사실은 밑에 있는 C 라이브러리 함수를 호출하여 이루어진 수면이다.
수면이 몇 밀리초인지 나타내는 롱 타입의 매개 변수가 있다.
주석을 읽으면sleep 방법의 의미는 현재 작업 수행 중인 라인을 수면(임시로 실행을 정지)시켜 지정한 밀리초수로 이 정밀도와 정확성을 시스템 시계와 스케줄러로 보장하는 것이다.그러나 라인은 자신이 가지고 있는 자물쇠를 방출하지 않는다.
이 메서드는 인터럽트 예외를 제거합니다.
sleep에서는 잠금 코드 예제를 해제하지 않습니다.
public class ThreadsleepDemo{

    private Object object = new Object();

    public static void main(String[] args) {

        ThreadsleepDemo threadsleepDemo = new ThreadsleepDemo();
        Thread thread1 = threadsleepDemo.new SleepDemoThread();
        thread1.setName("  1");
        Thread thread2 = threadsleepDemo.new SleepDemoThread();
        thread2.setName("  2");
        thread1.start();
        thread2.start();

    }

    class SleepDemoThread extends Thread{
        @Override
        public void run() {
            synchronized (object){
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
            }
        }
    }
}

출력 결과는 다음과 같습니다.
  1    
  1    
  2    
  2    

몇 번 더 운행할 수 있습니다. 1이 위에 있거나 2가 위에 있을 수도 있지만, 항상 한 여정이 다 운행되어야만 다른 노선을 운행할 수 있으며, 중간에 한 노선이 삽입되어 운행하지 않습니다.
방법
  /**
     * A hint to the scheduler that the current thread is willing to yield
     * its current use of a processor. The scheduler is free to ignore this
     * hint.
     *
     * 

Yield is a heuristic attempt to improve relative progression * between threads that would otherwise over-utilise a CPU. Its use * should be combined with detailed profiling and benchmarking to * ensure that it actually has the desired effect. * *

It is rarely appropriate to use this method. It may be useful * for debugging or testing purposes, where it may help to reproduce * bugs due to race conditions. It may also be useful when designing * concurrency control constructs such as the ones in the * {@link java.util.concurrent.locks} package. */ public static native void yield();


현재 스레드는 스케줄러에 대한 암시입니다. CPU 실행기의 현재 사용권을 양보하고 싶지만, 스케줄러는 이 알림을 무시할 수 있습니다.
Yeild는 CPU를 과도하게 사용할 수 있는 여러 스레드 사이에서 상대적인 진행률 향상을 위한 탐색 시도입니다.그것의 사용은 반드시 상세한 성능 분석과 기준 테스트를 결합하여 진행하여 그것이 확실히 기대하는 효과를 확보해야 한다.
이런 방법은 매우 드물다.그것은 디버깅이나 테스트에 유용할 수도 있고, 경쟁 조건에 따라 오류를 재현하는 데 도움이 될 수도 있다.병렬 제어 구조(예를 들어java.util.concurrent.locks 패키지의 병렬 제어 구조)를 설계할 때도 유용할 수 있다.
join 방법
Join씨는 세 가지 무거운 짐을 싣는 방법이 있어요.
join()
join(long millis)    
join(long millis,int nanoseconds)

두 번째 방법의 원본을 주로 보겠습니다.
    /**
     * Waits at most {@code millis} milliseconds for this thread to
     * die. A timeout of {@code 0} means to wait forever.
     *
     * 

This implementation uses a loop of {@code this.wait} calls * conditioned on {@code this.isAlive}. As a thread terminates the * {@code this.notifyAll} method is invoked. It is recommended that * applications not use {@code wait}, {@code notify}, or * {@code notifyAll} on {@code Thread} instances. */ 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; } } }


한 라인이 밀리초수를 지정한 후에 사라지는 것을 기다리는 것이다.파라미터가 없는join 방법은 사실join(0)을 호출한 것이다. 즉, 영원히 기다리는 것이다.그러나 원본 코드를 통해 while 순환에서 조건 판단, 즉 isAlive() 방법이 있음을 알 수 있다. 현재 라인이 살아있다면 계속 기다릴 수 있다는 뜻이다.
좀 멍하니 예를 들면 깊이 이해해야 한다.예를 들어 자기 전에 틱톡을 하고 싶다.
틱톡을 하는 일은 우리가 한 라인에 맡겨 완성한다.
public class ScanDouyin extends Thread{

    //        
    private int scanTime;

    public ScanDouyin(String name, int scanTime){
        super(name);
        scanTime = this.scanTime;
    }
    @Override
    public void run() {
        System.out.println(getName() + ":      ");
        try {
            //       
            sleep(scanTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(getName() +":     ,   ");
    }
}

이제 슬슬 잠을 청하는 라인입니다.
/**
 *       ,        
 */
public class ReadySleep extends Thread{

    private ScanDouyin scanDouyin;

    public ReadySleep(String name,ScanDouyin scanDouyin){
        super(name);
        this.scanDouyin = scanDouyin;
    }
    @Override
    public void run() {
        System.out.println(getName() + ":       ");
        try {
            //       
            scanDouyin.join();
           
            //          
            System.out.println("    ");
            sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(getName() + ":zzzzzzzz,     ");
    }

    public static void main(String[] args) {
        ScanDouyin scanDouyin = new ScanDouyin("     ",10000);
        ReadySleep readySleep = new ReadySleep("    ",scanDouyin);
        readySleep.start();
        scanDouyin.start();

    }
}

출력 결과는 다음과 같습니다.
    :       
     :      
     :     ,   
    
    :zzzzzzzz,     

여기에 우리가 설정한 틱톡의 시간은 10s이고 잠자는 라인의 실행 시간은 100ms, 즉 0.1s이다.
잠자는 라인에서 틱톡 라인을 닦는 Join 방법을 사용했기 때문에 잠자는 라인은 틱톡(틱톡 라인이 실행되고 라인이 사라질 때까지)을 기다려야 잠을 잘 수 있다.
이로써, 만약 어떤 라인이 다른 라인 t에서 t.join () 을 호출한다면, 이 라인은 목표 라인 t가 끝날 때까지 끊기고, (즉 t.isAlive () 방법이 가짜로 되돌아갈 것이다.)

좋은 웹페이지 즐겨찾기