자바 동시성 : 세 가지 방법으로 생성 된 Java 스레드 : Java 스레드는 세 자바에게 동시 프로그램을 만들 수있는 방법입니다

자바 동시성 : 세 가지 방법으로 생성 된 Java 스레드

디렉토리

소개

일상 개발 작업에서는 멀티 스레드 개발이 스레드의 이해 좋은을 가지고 좋은 프로그래머를위한 필수적인 기술이 될 것이 분명 말할 수있다, 나는 자바 프로그래머 오전과 자바 언어 자체는 매우 성숙 스레드의 개발을 지원하기 위해 오늘 우리는 자바 스레드를 생성하는 방법에 대한 자세한 내용을 보려면, 문에 있습니다.

스레드를 만드는 세 가지 방법

자바는 세 가지 주요 방법이 있습니다 스레드를 만들 수 있습니다 :

1, 상속 스레드 클래스

2, Runnable를 구현

3, 사용하여 호출 가능하고 미래 스레드를 생성

이러한 구현 예는 세 가지 방법을 후술과 그들 사이의 대조된다.

첫째, Thread 클래스 상속

단계 :

1, 서브 클래스의 상속 스레드 스레드 클래스를 생성

2, 재정의 run () 메소드는, 프로그램 실행 방법, 프로그램이 스레드 시작 후 시작됩니다 방법의 스레드로 실행해야

2, 클래스의 인스턴스를 생성하고 스레드를 시작하기 위해 객체의 start () 메서드를 호출

다음 샘플 코드는 다음과 같습니다

public class ThreadDemo extends Thread{
    @Override
    public void run() {
        super.run();
        System.out.println("需要运行的程序。。。。。。。。");
    }

    public static void main(String[] args) {
        Thread thread = new ThreadDemo();
        thread.start();
    }
}

main 메소드를 실행 한 후, 프로그램은 왜 실행 () 메소드를 재정의해야합니다, 그것은 죽을와 함께 실행 후, 스레드를 실행 () 메서드 내부의 내용을 실행합니다?

소스 방법은 스레드의 실행 () 메소드는 실제로 아무 상관이 발견을 클릭합니다

public void run() {
    if (target != null) {
        target.run();
    }
}

public abstract void run();

실행은 () 프로그램을 실행 할 필요가없는 경우, 스레드는 서거 직후에 시작합니다. 우리는 당신이 스레드의 run () 메소드를 다시 작성해야 뭔가를하고 싶다. 동시에, 또한 스레드가 제대로 실행 할 수있다, 시작 () 메서드를 호출하기 시작하지만, 직접 방법도 컴파일 할 수 있습니다) (실행 호출 주목해야한다 :

public static void main(String[] args) {
    Thread thread = new ThreadDemo();
    thread.run();
}

이것은 단지 일반 메서드 호출하고, 새로운 스레드에서 스레드는 그 자체를 의미 손실 될 수 없습니다.

둘째, Runnable를 구현

도 1은 구현의 Runnable 인터페이스는, 인터페이스와 재 run () 메소드는, 상기 방법은 계속 실행하도록 지정하는 프로그램을 포함하는 스레드 클래스를 정의한다.

(2)는 대상 파라미터로 전달하는 클래스 인스턴스의 Runnable를 생성하고 스레드 클래스의 인스턴스를 생성한다.

3, 스레드를 시작하는 시작 Thread 클래스 인스턴스 () 메서드를 호출합니다.

public class RunnableDemo implements Runnable{
    @Override
    public void run() {
        System.out.println("我是Runnable接口......");
    }
    public static void main(String[] args) {

        RunnableDemo demo = new RunnableDemo();
        Thread thread = new Thread(demo);
        thread.start();
    }
}

이것은 방법에 멀티 스레드 객체를 생성 할 수있는 인터페이스, 상속 스레드 유연성이 많이있을 것보다 방법,하지만 필요성을 기반으로 오픈 소스를 찾을 수 때의 Runnable 클래스의 인스턴스가 구현 현재 스레드 클래스에 할당 된 매개 변수로 전달 된 대상, 대상 및 프로그램 실행 ()는 대상의 run () 메소드로 할당에서 실행됩니다.

public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}

private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc) {
                      
        ...........这里省略部分源码..........
        
        this.target = target;
        setPriority(priority);
        if (parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        tid = nextThreadID();
    }
    
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

셋째, 사용 호출 가능하고 미래 스레드를 생성

호출 가능 스레드를 생성하고 Runnable를 인터페이스 모드가 호출 인터페이스가 실행 스레드로 호출 () 메소드를 제공하고, 실행 가능한 인터페이스를 동시에 실행 () 메소드를 제공하며, 그 차이가 매우 유사한 스레드 사용하여 만든, () 메서드 호출을 할 수 있습니다 값을 반환하지만, FutureTask 호출 가능 객체 클래스를 포장해야합니다.

public interface Callable<V> {
    
    V call() throws Exception;
}

단계 :

1) (구현 호출 인터페이스가 호출을 달성한다는 방법 클래스를 만들

2, 방법의 값을 돌려줍니다 ()를 호출 호출 가능 객체를 캡슐화 FutureTask 호출 가능 객체 클래스에 의해 포장 클래스 인스턴스 호출 가능을 만듭니다.

3, FutureTask 오브젝트는 새로운 스레드를 스레드의 스레드 인스턴스를 생성하고 시작하는 타겟 인수로 생성된다.

4, 반환 값을 얻을 수 FutureTask 객체의 get 메소드를 호출합니다.

public class CallableDemo implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int i = 1;
        return i;
    }

    public static void main(String[] args) {
        CallableDemo demo = new CallableDemo();
        FutureTask<Integer> task = new FutureTask<Integer>(demo);

        new Thread(task).start();
        try {

            System.out.println("task 返回值为:" + task.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

기본 방법을 실행 한 결과, 다음과 같은 결과를 출력한다 :

task 返回值为:1

설명, task.get ()는 결과의 () 메서드 호출을 반환한다. 그런 다음 그 내부는 그것을 달성하는 방법이다. 메소드 FutureTask 먼저 개방 구조는, 우리는 내부가 그의 호출 가능 호출 가능 부재를 매개 변수로서 현재 인스턴스 목적은 볼 수

public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}

시작 작업이 그 실행 방법이 전화 호출 가능 () 메소드를 실행하는 경우 사이에, 상기 상태 변수의 부재, NEW로 설정하고,

public void run() {
    if (state != NEW ||
        !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                     null, Thread.currentThread()))
        return;
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                //把call()的返回结果复制给result
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                setException(ex);
            }
            if (ran)
                //将结果设置给其他变量
                set(result);
        }
    } finally {
        // runner must be non-null until state is settled to
        // prevent concurrent calls to run()
        runner = null;
        // state must be re-read after nulling runner to prevent
        // leaked interrupts
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}
protected void set(V v) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            //把传过来的值赋值给outcome成员
            outcome = v;
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
            finishCompletion();
        }
    }

일련의 과정을 통해 실행 한 후 ()를 호출 결과에 할당 run () 메소드의 결과를 반환하고 결과는 인수에 task.get () 메소드를 호출 할 때,이 방법은, 앞으로 나올 것입니다 값입니다 얻어진 결과가 반환됩니다.

public V get() throws InterruptedException, ExecutionException {
    int s = state;
    if (s <= COMPLETING)
        s = awaitDone(false, 0L);
    return report(s);
}
private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            //返回outcome的值
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }

보는 바와 같이 나는 독자가 더 기본 자바 소스 코드를 볼 수 있습니다 것이 좋습니다 더 무료입니다, 그래서 소스 코드의 작동 논리는, 코드를 이해하기 쉽게, 아주 분명하다, 이것은 우리가 더 기능이 구현되는 방법을 이해하는 데 도움이됩니다.

세 가지 방법의 비교

음, 스레드 인스턴스를 생성하는 방법은 세 가지가 비교에서 말을 계속했다 및 다.

구현에서 호출 인터페이스 인터페이스 사용 Runnable를이 같은 방식은 기본적으로, 메소드 본문의 구분은 사실, 세 가지 방법은 두 가지 범주로 분류하기 위해, 그것이, 호출 가능는 반환 값을 가질 수 있습니다 달성하고, Thread 클래스 상속의 사용이다 상속 분석 할 수있다.

1, Thread 클래스 상속을 사용합니다 :

  • 장점 : 간단한 코딩하고, 현재 스레드를 얻을 필요가있을 때, 당신은 직접 사용할 수 있습니다
  • 단점 : 자바는 단일 상속을 지원하기 때문에 그렇게 할 수 있습니다 클래스 상속 스레드 후하지 상속 다른 부모

2, 호출 가능 인터페이스 Runnable 인터페이스 방식을 사용하여 :

  • 장점 :

더 유연하지만, 스레드 구현 인터페이스 할 수도 상속 다른 부모가.

이러한 방법으로, 여러 스레드는 대상 개체는 상황에 멀티 스레드 처리 자원에 이상적입니다 공유 할 수 있습니다.

호출 인터페이스 모드는 반환 값을 캡처 할 수 있습니다.

  • 단점 :

인코딩 약간 더 복잡 포인트, 우리는 더 많은 개체를 만들어야합니다.

현재 스레드에 액세스하려는 경우는 Thread.currentThread () 메소드가 필요합니다.

전반적으로,이 분류는 자신의 장점과 단점을 가지고 있지만 사실 후자의 상대적 장점과 정상적인 상황에서 그것을 지적 단점의 가치는, 모든 직후 방법과 인터페이스, 단일 상속 약점을 스레드를 생성하는 것이 좋습니다 그것은 아주 큽니다.






소개

일상 개발 작업에서는 멀티 스레드 개발이 스레드의 이해 좋은을 가지고 좋은 프로그래머를위한 필수적인 기술이 될 것이 분명 말할 수있다, 나는 자바 프로그래머 오전과 자바 언어 자체는 매우 성숙 스레드의 개발을 지원하기 위해 오늘 우리는 자바 스레드를 생성하는 방법에 대한 자세한 내용을 보려면, 문에 있습니다.

스레드를 만드는 세 가지 방법

자바는 세 가지 주요 방법이 있습니다 스레드를 만들 수 있습니다 :

1, 상속 스레드 클래스

2, Runnable를 구현

3, 사용하여 호출 가능하고 미래 스레드를 생성

이러한 구현 예는 세 가지 방법을 후술과 그들 사이의 대조된다.

첫째, Thread 클래스 상속

단계 :

1, 서브 클래스의 상속 스레드 스레드 클래스를 생성

2, 재정의 run () 메소드는, 프로그램 실행 방법, 프로그램이 스레드 시작 후 시작됩니다 방법의 스레드로 실행해야

2, 클래스의 인스턴스를 생성하고 스레드를 시작하기 위해 객체의 start () 메서드를 호출

다음 샘플 코드는 다음과 같습니다

public class ThreadDemo extends Thread{
    @Override
    public void run() {
        super.run();
        System.out.println("需要运行的程序。。。。。。。。");
    }

    public static void main(String[] args) {
        Thread thread = new ThreadDemo();
        thread.start();
    }
}

main 메소드를 실행 한 후, 프로그램은 왜 실행 () 메소드를 재정의해야합니다, 그것은 죽을와 함께 실행 후, 스레드를 실행 () 메서드 내부의 내용을 실행합니다?

소스 방법은 스레드의 실행 () 메소드는 실제로 아무 상관이 발견을 클릭합니다

public void run() {
    if (target != null) {
        target.run();
    }
}

public abstract void run();

실행은 () 프로그램을 실행 할 필요가없는 경우, 스레드는 서거 직후에 시작합니다. 우리는 당신이 스레드의 run () 메소드를 다시 작성해야 뭔가를하고 싶다. 동시에, 또한 스레드가 제대로 실행 할 수있다, 시작 () 메서드를 호출하기 시작하지만, 직접 방법도 컴파일 할 수 있습니다) (실행 호출 주목해야한다 :

public static void main(String[] args) {
    Thread thread = new ThreadDemo();
    thread.run();
}

이것은 단지 일반 메서드 호출하고, 새로운 스레드에서 스레드는 그 자체를 의미 손실 될 수 없습니다.

둘째, Runnable를 구현

도 1은 구현의 Runnable 인터페이스는, 인터페이스와 재 run () 메소드는, 상기 방법은 계속 실행하도록 지정하는 프로그램을 포함하는 스레드 클래스를 정의한다.

(2)는 대상 파라미터로 전달하는 클래스 인스턴스의 Runnable를 생성하고 스레드 클래스의 인스턴스를 생성한다.

3, 스레드를 시작하는 시작 Thread 클래스 인스턴스 () 메서드를 호출합니다.

public class RunnableDemo implements Runnable{
    @Override
    public void run() {
        System.out.println("我是Runnable接口......");
    }
    public static void main(String[] args) {

        RunnableDemo demo = new RunnableDemo();
        Thread thread = new Thread(demo);
        thread.start();
    }
}

이것은 방법에 멀티 스레드 객체를 생성 할 수있는 인터페이스, 상속 스레드 유연성이 많이있을 것보다 방법,하지만 필요성을 기반으로 오픈 소스를 찾을 수 때의 Runnable 클래스의 인스턴스가 구현 현재 스레드 클래스에 할당 된 매개 변수로 전달 된 대상, 대상 및 프로그램 실행 ()는 대상의 run () 메소드로 할당에서 실행됩니다.

public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}

private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc) {
                      
        ...........这里省略部分源码..........
        
        this.target = target;
        setPriority(priority);
        if (parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        tid = nextThreadID();
    }
    
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

셋째, 사용 호출 가능하고 미래 스레드를 생성

호출 가능 스레드를 생성하고 Runnable를 인터페이스 모드가 호출 인터페이스가 실행 스레드로 호출 () 메소드를 제공하고, 실행 가능한 인터페이스를 동시에 실행 () 메소드를 제공하며, 그 차이가 매우 유사한 스레드 사용하여 만든, () 메서드 호출을 할 수 있습니다 값을 반환하지만, FutureTask 호출 가능 객체 클래스를 포장해야합니다.

public interface Callable<V> {
    
    V call() throws Exception;
}

단계 :

1) (구현 호출 인터페이스가 호출을 달성한다는 방법 클래스를 만들

2, 방법의 값을 돌려줍니다 ()를 호출 호출 가능 객체를 캡슐화 FutureTask 호출 가능 객체 클래스에 의해 포장 클래스 인스턴스 호출 가능을 만듭니다.

3, FutureTask 오브젝트는 새로운 스레드를 스레드의 스레드 인스턴스를 생성하고 시작하는 타겟 인수로 생성된다.

4, 반환 값을 얻을 수 FutureTask 객체의 get 메소드를 호출합니다.

public class CallableDemo implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int i = 1;
        return i;
    }

    public static void main(String[] args) {
        CallableDemo demo = new CallableDemo();
        FutureTask<Integer> task = new FutureTask<Integer>(demo);

        new Thread(task).start();
        try {

            System.out.println("task 返回值为:" + task.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

기본 방법을 실행 한 결과, 다음과 같은 결과를 출력한다 :

task 返回值为:1

설명, task.get ()는 결과의 () 메서드 호출을 반환한다. 그런 다음 그 내부는 그것을 달성하는 방법이다. 메소드 FutureTask 먼저 개방 구조는, 우리는 내부가 그의 호출 가능 호출 가능 부재를 매개 변수로서 현재 인스턴스 목적은 볼 수

public FutureTask(Callable<V> callable) {
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}

시작 작업이 그 실행 방법이 전화 호출 가능 () 메소드를 실행하는 경우 사이에, 상기 상태 변수의 부재, NEW로 설정하고,

public void run() {
    if (state != NEW ||
        !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                     null, Thread.currentThread()))
        return;
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                //把call()的返回结果复制给result
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                setException(ex);
            }
            if (ran)
                //将结果设置给其他变量
                set(result);
        }
    } finally {
        // runner must be non-null until state is settled to
        // prevent concurrent calls to run()
        runner = null;
        // state must be re-read after nulling runner to prevent
        // leaked interrupts
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}
protected void set(V v) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            //把传过来的值赋值给outcome成员
            outcome = v;
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
            finishCompletion();
        }
    }

일련의 과정을 통해 실행 한 후 ()를 호출 결과에 할당 run () 메소드의 결과를 반환하고 결과는 인수에 task.get () 메소드를 호출 할 때,이 방법은, 앞으로 나올 것입니다 값입니다 얻어진 결과가 반환됩니다.

public V get() throws InterruptedException, ExecutionException {
    int s = state;
    if (s <= COMPLETING)
        s = awaitDone(false, 0L);
    return report(s);
}
private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            //返回outcome的值
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }

보는 바와 같이 나는 독자가 더 기본 자바 소스 코드를 볼 수 있습니다 것이 좋습니다 더 무료입니다, 그래서 소스 코드의 작동 논리는, 코드를 이해하기 쉽게, 아주 분명하다, 이것은 우리가 더 기능이 구현되는 방법을 이해하는 데 도움이됩니다.

세 가지 방법의 비교

음, 스레드 인스턴스를 생성하는 방법은 세 가지가 비교에서 말을 계속했다 및 다.

구현에서 호출 인터페이스 인터페이스 사용 Runnable를이 같은 방식은 기본적으로, 메소드 본문의 구분은 사실, 세 가지 방법은 두 가지 범주로 분류하기 위해, 그것이, 호출 가능는 반환 값을 가질 수 있습니다 달성하고, Thread 클래스 상속의 사용이다 상속 분석 할 수있다.

1, Thread 클래스 상속을 사용합니다 :

  • 장점 : 간단한 코딩하고, 현재 스레드를 얻을 필요가있을 때, 당신은 직접 사용할 수 있습니다
  • 단점 : 자바는 단일 상속을 지원하기 때문에 그렇게 할 수 있습니다 클래스 상속 스레드 후하지 상속 다른 부모

2, 호출 가능 인터페이스 Runnable 인터페이스 방식을 사용하여 :

  • 장점 :

더 유연하지만, 스레드 구현 인터페이스 할 수도 상속 다른 부모가.

이러한 방법으로, 여러 스레드는 대상 개체는 상황에 멀티 스레드 처리 자원에 이상적입니다 공유 할 수 있습니다.

호출 인터페이스 모드는 반환 값을 캡처 할 수 있습니다.

  • 단점 :

추천

출처www.cnblogs.com/xues/p/11810122.html