Java Thread Four Creation Methods

异步与线程池

1、初始化线程的4种方式

1)、继承Thread 2)、ImplementationRunnableInterface 3)、ImplementationCallableInterface+FutureTask(可以拿到Return结果,可以处理异常) 4)、Thread Pool

方式1和方式2:主进程无法GetThread的运算结果。不适合当前场景。

方式3:主进程可以GetThread的运算结果,但是不利于控制Server中的Thread资源。可以导致Server资源耗尽。 方式4:通过如下两种方式初始化Thread Pool

Executors.newFiexed ThreadPool(3);
//或者
new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,TimeUnit unit, workQueue,threadFactory,handler);

方式1、继续Thread

/**
 * @description: 继承Thread
 * @author: <a href="mailto:batis@foxmail.com">清风</a>
 * @date: 2022/3/10 21:06
 * @version: 1.0
 */
public class MyThread {
    public static void main(String[] args) {
        System.out.println("启动main方法开始");

        OneMyThread oneMyThread = new OneMyThread();
        oneMyThread.start();

        System.out.println("结束main方法");

    }

    public static class OneMyThread extends Thread{
        @Override
        public void run() {
            System.out.println("当前线程:"+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果:"+i);
        }
    }
}

Run结果:

启动main方法开始
结束main方法
当前线程:22
运行结果:5

方式2、实现Runable接口

/**
 * @description: 实现Runnable接口
 * @author: <a href="mailto:batis@foxmail.com">清风</a>
 * @date: 2022/3/10 21:06
 * @version: 1.0
 */
public class MyThread {
    public static void main(String[] args) {
        System.out.println("启动main方法开始");
        
        TwoMyThread twoMyThread = new TwoMyThread();
        new Thread(twoMyThread).start();

        System.out.println("结束main方法");

    }

    /**
     * 实现Runnable接口
     */
    public static class TwoMyThread implements Runnable {

        @Override
        public void run() {
            System.out.println("当前线程:"+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果:"+i);
        }
    }
}

Run结果:

启动main方法开始
结束main方法
当前线程:22
运行结果:5

方式3、实现Callable泛型接口

/**
 * @description: 继承Thread
 * @author: <a href="mailto:batis@foxmail.com">清风</a>
 * @date: 2022/3/10 21:06
 * @version: 1.0
 */
public class MyThread {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("启动main方法开始");

        FutureTask<Integer> futureTask = new FutureTask<>(new ThreeMyThread());
        new Thread(futureTask).start();
        //等待线程执行完成,返回结果
        Integer i = futureTask.get();
        System.out.println("线程执行完,返回结果:"+i);

        System.out.println("结束main方法");

    }

    /**
     * 实现Callable<T>泛型接口
     */
    public static class ThreeMyThread implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程:"+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果:"+i);
            return i;
        }
    }
}

Run结果:

启动main方法开始
当前线程:22
运行结果:5
线程执行完,返回结果:5
结束main方法

注意:结果的顺序,可以看到是一个阻塞等待

通过FutureTask类Source Code可以看到,FutureTask不仅可以接受Callable还可以接收Runnable.

FutureTaskSource Code如下:

public class FutureTask<V> implements RunnableFuture<V> {
    /**
     * Creates a {@code FutureTask} that will, upon running, execute the
     * given {@code Runnable}, and arrange that {@code get} will return the
     * given result on successful completion.
     * * @param runnable the runnable task
     * @param result the result to return on successful completion. If
     * you don't need a particular result, consider using
     * constructions of the form:
     * {@code Future<?> f = new FutureTask<Void>(runnable, null)}
     * @throws NullPointerException if the runnable is null
     */
    public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }

FutureTaskImplementationRunnableFutureInterface:RunnableFuture最终是继承的Runnable。

package java.util.concurrent;

/**
 * A {@link Future} that is {@link Runnable}. Successful execution of
 * the {@code run} method causes completion of the {@code Future}
 * and allows access to its results.
 * @see FutureTask
 * @see Executor
 * @since 1.6
 * @author Doug Lea
 * @param <V> The result type returned by this Future's {@code get} method
 */
public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

方式4、直接提交线程池,线程池会自动开启任务。

每次通过new Thread()CreateThreadProblem:导致资源耗尽。以上三种Start方式都不用。应该将所有Asynchronous多Thread任务交给Thread PoolExecute。

Thread Pool:

package com.yanxizhu.family.booking;

import java.util.concurrent.*;

/**
 * @description: 继承Thread
 * @author: <a href="mailto:batis@foxmail.com">清风</a>
 * @date: 2022/3/10 21:06
 * @version: 1.0
 */
public class MyThread {

    //应保证,当前系统中线程池只有一两个,每个异步任务,提交给线程池自己执行。
    public static ExecutorService executorService = Executors.newFixedThreadPool(10);
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("启动main方法开始");
        
        executorService.submit(new TwoMyThread()); //有返回值
        //每个异步任务,提交给线程池自己执行。
        executorService.execute(new TwoMyThread());//无返回值

        System.out.println("结束main方法");

    }

    /**
     * 实现Runnable接口
     */
    public static class TwoMyThread implements Runnable {

        @Override
        public void run() {
            System.out.println("当前线程:"+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果:"+i);
        }
    }
}

Run结果:

启动main方法开始
结束main方法
当前线程:22
运行结果:5

UsageThread Pool带来的好处:

1、降低资源的消耗 通过重复利用已经Create好的Thread降低Thread的Create和销毁带来的损耗 2、提高响应速度 因为Thread Pool中的Thread数没有超过Thread Pool的最大上限时,有的Thread处于等待分配任务的状态,当任务来时无需Create新的Thread就能Execute 3、提高Thread的可管理性 Thread Pool会根据当前系统特点对池内的Thread进行Optimization处理,减少Create和销毁Thread带来的系统开销。无限的Create和销毁Thread不仅消耗系统资源,还降低系统的稳定性,UsageThread Pool进行统一分配

总结区别

1、直接继承Thread、ImplementationRunnableInterface:不能直接得到Return值。

2、ImplementationCallable泛型Interface:可以得到Return值。

3、继承Thread、ImplementationRunnableInterface、ImplementationCallable泛型Interface,都不能达到控制资源的效果。

4、只有Thread Pool可以控制资源,Performance稳定。