正しい姿勢スレッド、マルチラインの同時基礎

最終的にはマルチスレッドのアプローチはいくつかありますか?

JAVAマルチスレッドの実装では、オンラインや書籍が異なる意見を持っているかどうか、いくつかの2つを言うために、いくつかのは4、ちょうどBaiduは、我々は答えの様々を見ることができますがありますと言います。

image.md.png

それは本当に、いくつかの一つですか?のは、APIドキュメントのJAVAを見てみましょうします。https://docs.oracle.com/javase/9​​/docs/api/java/lang/Thread.html

私たちは、はっきり文書から見ることができる、マルチスレッド、2つの方法がありますが、1注文でクラス宣言のサブクラスでThread、ステートメントの実現があるRunnableインタフェースクラス。

imageab3074b7eba1911e.md.png

2つの実装を比較します

実行可能なインタフェースを実装します。

/**
 * @author Chen
 * @Description 使用runnable接口实现多线程
 * @create 2019-11-04 21:38
 */
public class RunnableStyle implements Runnable{
    public static void main(String[] args) {
        Thread thread = new Thread(new RunnableStyle());
        thread.start();
    }

    @Override
    public void run() {
        System.out.println("使用runnable接口实现多线程");
    }
}

Threadクラスの継承:

/**
 * @author Chen
 * @Description 使用Thread方式实现多线程
 * @create 2019-11-04 21:41
 */
public class ThreadStyle extends Thread{
    public static void main(String[] args) {
        Thread thread = new ThreadStyle();
        thread.start();
    }

    @Override
    public void run() {
        System.out.println("使用Thread类实现多线程");
    }
}

Runableを使用するか、スレッド?

彼らはマルチスレッド達成することができますので、我々はカジュアル作成する実用的な方法を選択するために使用するか、それができなければなりませんか?

答えは達成することであるRunableずっといい。

主な理由は次のとおりです。

1. デカップリング観点、マルチスレッドタスクの実行されるべきである(すなわち、実行方法の内容である)Threadクラスが切り離され、

むしろ、彼らは一緒に書かれていません。

2.継承を使用している場合はThread、我々は新しいタスクを作成するたびにのみ、別のスレッドを作成することができ、マルチスレッドを実装するクラスを、そしてこの損失が比較的大きい、我々はそうで作成、破棄してする必要があります。使用するRunnableインタフェースは、その後のフォローアップは、我々は、スレッドプールを使用することができますので、あなたができる新しいスレッドによる損失を減らします。

3. JAVAは単一継承なので、一度は継承されたThread他のクラスに継承することができなくなり、プログラムのスケーラビリティを制限します。

Runableスレッドは、スレッドとの違いを作成するには?

使用しRunable、我々が使用している作成する方法をThread、パラメータを使用してコンストラクタクラスThreadを作成する方法を、の使用であり、Thread引数なしでクラスのコンストラクタは、これらのメソッドの両方を書き換えるRunのは、見てみましょう、この方法を参照ThreadRunメソッドクラスは、達成するためにどのようにされています。

    /* What will be run. */
    private Runnable target;

    /**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

これらは、の一部であるThreadクラスのソースコードは、我々が実行見ることができるrun方法の時間を、それが最初の着信かどうかを決定するRunable渡された場合、インタフェースの実装クラスインターフェースの実装クラスのrunメソッドを渡されない場合、直接実行されますサブクラスは、オーバーライドrunメソッドをので、本質的に、これら2つの方法の本質は、実装されているRun方法が、Run異なるソース方法から。

神話

スレッドプールのスレッドを作成すると、新しいスレッドの方法とみなすことができます

/**
 * @author Chen
 * @Description 使用线程池创建线程
 * @create 2019-11-05 9:40
 */
public class ThreadPoolStyle {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i <1000 ; i++) {
            executorService.submit(new Task());
        }
    }

    static class  Task implements Runnable{
        @Override
        public void run() {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName());
        }
    }
}

以下は、簡単に見ているexcutors内部スレッドを作成する方法:

あなたは、新しいスレッドコードスレッド・プールには、以下を渡すことで内部を見ることができRunnable、その後、new thread外装には、作成した方法が同じではないように見えますが、原理は通過であるもののので、作成するために、Runnableマルチスレッドインタフェースを実現します。

    /**
     * The default thread factory
     */
    static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

FutureTaskを通じて呼び出し可能と作成のスレッドが新しいスレッドの方法とみなすことができます

よるCallableFuture

/**
 * @author Chen
 * @Description 使用Callable、Future以及FutureTask
 * @create 2019-11-05 10:03
 */
public class FutureTaskStyle {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<String> future = executorService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.sleep(500);
                return "future result";
            }
        });
        System.out.println(System.currentTimeMillis());
        System.out.println(future.get());
        System.out.println(System.currentTimeMillis());
    }
}

よるCallableFutureTask

/**
 * @author Chen
 * @Description 使用Callable、Future以及FutureTask
 * @create 2019-11-05 10:03
 */
public class FutureTaskStyle {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.sleep(500);
                return "future result";
            }
        });
        new Thread(futureTask).start();
        System.out.println(System.currentTimeMillis());
        System.out.println(futureTask.get());
        System.out.println(System.currentTimeMillis());
    }
}

使用ctrl+alt+uビューのFutureTask継承グラフ:あなたが見ることができますRunableFuture継承FutureRunnableインターフェース、FutureTaskだけでなく、実現RunableFutureするので、FutureTaskまた間接的に実装Runableインターフェイスを。したがって、この方法および使用Runnableの原則を達成するための方法は同じです。

image7f03cb1928004065.md.png

タイマーにより、

/**
 * @author Chen
 * @Description 使用定时器创建新的线程
 * @create 2019-11-05 10:26
 */
public class TimmerStyle {
    public static void main(String[] args) {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        },1000,1000);

    }
}

見てTimerTaskも実装Runnableインタフェースは、本質的には、それが使用するRunnableインターフェイスを作成します。

匿名内部クラスまたはラムダ式で

/**
 * @author Chen
 * @Description 使用匿名内部类 和lamada表达式实现多线程
 * @create 2019-11-05 10:36
 */
public class AnonymousInnerClassStyle {
    public static void main(String[] args) {
        //匿名内部类
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        }).start();

        //Lambda 表达式
        new Thread(()-> System.out.println(Thread.currentThread().getName())).start();

    }
}

この形式は、単に構文が効果を達成するために、実際には、匿名内部クラスとラムダ式を少し変更と同じですが、交換の文言れます。

概要

マルチスレッド終了にはいくつかの方法がありますか?別の観点からは、ビューのマルチスレッドの性質の点の実現から、異なる答えが存在するであろう、二つあり、一つは達成することでRunnable、一方が継承されるインターフェースThreadクラスとコード実装レベルから、多くがあり、そのようなスレッドプール、などFutureTask匿名内部クラスとLambda表現。

実際には、原則を見ては、と呼ばれ、自然の中で2つの実装では同じであるThreadクラスのrunメソッド、およびrun、着信があれば方法は、裁判官を持っているrunnableの実装に、空ではないrun方法で自分自身内のコード。

通常の状況下で、我々は、使用するRunable主に次のような理由から、新しい道を通すためのインタフェースを:

結合の表示、タスクのコード提出するの手続き点からThreadクラスコードが低いカップリングから分離されます。

観点からJavaは単一継承であるため、継承の使用、拡張することができるThead方法は、クラスは、プログラムのクラスの拡張を低減する、他の基本クラスに継承することができません。

ビューのリソース消費ポイントの観点から、使用Runnable我々は、スレッドプールのスレッドを管理するために使用できる方法は、新しいスレッドがスレッドや他の資源の枯渇に起因する破壊を減らすことができます。

おすすめ

転載: www.cnblogs.com/chen88/p/11797182.html