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稳定。