前言
本文是学习线程时的简要记录,仅供参考,如有纰漏,请大家指正。
一、初始化线程的几种方式?
- 1、继承Thread
- 2、实现Runnable接口
- 3、实现Callable接口+FutureTask(可以拿到返回结果,可以处理异常)
- 4、创建线程池的方式。
方式1和方式2:主线程无法获取线程的运算结果。
方式3:主线程可以获取线程的运算结果,但是不利于控制服务器中的线程资源,可能导致服务器资源耗尽。
方式4:可以通过如下方式初始化线程池。
通过线程池初始化,性能稳定,也可以获取执行结果,并捕获异常。但是在业务复杂情况下,一个异步调用可能会依赖于另一个异步调用的执行结果。
Executors.newFixedThreadPool(10);
//或者
new ThreadPoolExecutor(
corePoolSize 5,
maximumPoolSize 200,
keepAliveTime 10,
TimeUnit TimeUnit.SECONDS,
BlockingQueue<Runnable> new LinkedBlockingQueue<>(10000),
ThreadFactory Executors.defaultThreadFactory(),
RejectedExecutionHandler new ThreadPoolExecutor.AbortPolicy()
);
初始化线程示例代码如下:
public class ThreadTest {
public static ExecutorService service = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("main....start");
//1、继承Thread
Thread01 thread01 = new Thread01();
thread01.start();
//2、实现Runnable接口
Runnable01 runnable01 = new Runnable01();
new Thread(runnable01).start();
//3、实现Callable接口+FutureTask(可以拿到返回结果,可以处理异常)
FutureTask<Integer> integerFutureTask = new FutureTask<>(new Callable01());
new Thread(integerFutureTask).start();
//等待整个线程执行结束,获取返回结果,阻塞等待
Integer integer = integerFutureTask.get();
//4、线程池
service.execute(new Runnable01());
//new ThreadPoolExecutor()
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
5,
200,
10,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(10000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
System.out.println("main....end");
}
//1、继承Thread
public static class Thread01 extends Thread{
@Override
public void run() {
System.out.println("当前线程:"+Thread.currentThread().getId());
int i=10/2;
System.out.println("运行结果:"+i);
}
}
public static class Runnable01 implements Runnable{
@Override
public void run() {
System.out.println("当前线程:"+Thread.currentThread().getId());
int i=10/2;
System.out.println("运行结果:"+i);
}
}
public static class Callable01 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;
}
}
}
二、线程池创建的七大参数
1.线程池各参数的含义
-
int corePoolSize:[5]核心线程数【5个一直存在除非设置了allowCoreThreadTimeOut】,线程池创建好以后就准备就绪的线程数量,就等待来接收异步任务去执行。
-
int maximumPoolSize:最大线程数量;控制资源并发的。
-
long keepAliveTime:存活时间,如果当前数量大于核心线程数量。线程空闲的时间大于存活时间,释放除核心线程外的超存活时间的空闲线程。
-
TimeUnit unit:时间单位。
-
BlockingQueue workQueue:阻塞队列,如果任务有很多,就会将目前多的任务放在队列里面。只要有空闲的线程,就会去队列中取出新的任务继续执行。
-
ThreadFactory threadFactory:线程的创建工厂,也可以自定义。
-
RejectedExecutionHandler handler:如果队列满了按照我们指定的拒绝策略拒绝执行任务。
2.线程的运行流程
1、线程池创建好,准备好core数量的核心线程,准备接收任务
- 1.1、core满了,就将再进来的任务放进阻塞队列中,空闲的core就会自己去阻塞队列获取任务执行
- 1.2、阻塞队列满了,就直接开新线程执行,最大只能开到max指定的数量
- 1.3、max满了就用RejectedExecutionHandler拒绝任务
- 1.4、max都执行完了,在指定的时间keepAliveTime以后,释放,max-core数量的线程
2、线程池运行例题
假如一个线程池,corePoolSize:7,maximumPoolSize:20,workQueue:50,有100个线程同时进来,怎么分配?
先用7个直接可以得到执行,接下来50个进入阻塞队列排队,再多开13个线程继续执行。现在70个线程已经分配,剩下30个线程使用设置好的拒绝策略。
总结
本文为学习中的笔记,以后会继续完善。