【Java实战】线程池 并发 并行 生命周期(详细解释)

【Java实战】线程池 并发 并行 生命周期(详细解释)

线程池:

一种复用线程的技术

不使用线程池的问题:

用户每提出一个需求,都要创建一个新的线程。

创建线程池的方法:

JDK 5.0起提供了一个代表线程池的接口:ExecutorService。

方式一:

使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象。

public ThreadPoolExecutor(

int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler)

参数详细解析

参数一: corePoolSize(核心线程数)

意义:线程池中保持存活的最小线程数量,即使它们处于空闲状态。

参数二: maximumPoolSize(最大线程数)

意义:线程池允许创建的最大线程数量。

参数三:keepAliveTime(线程空闲时间)

意义:当线程数超过核心线程数时,多余的空闲线程在终止前等待新任务的最长时间。

参数四:unit(时间单位)

意义:keepAliveTime参数的时间单位。

参数五:workQueue(工作队列)

意义:用于保存等待执行的任务的阻塞队列。

参数六:threadFactory(线程工厂)

意义:用于创建新线程的工厂。

参数七:handler(拒绝策略)

意义:当线程池和工作队列都达到饱和状态时(即线程数达到maximumPoolSize且队列已满),对新任务采取的处理策略。

类比理解:

参数一 正式工:3

参数二 最大员工数:5 临时工:2

参数三四 临时工空闲多久被开除

参数五 客人排队的地方

参数六 负责招聘的hr

参数七 忙不过来怎么办?

代码演示:

public class ThreadPoolTest{

public static void main(String[] args){

new ThreadPoolExecutor(3,5,8,TimeUnit.SECOND,new LinkedBlockingQuene<>(),Executors.defaultThreadFactory(),new ThreadPoolExexutor.AbortPolicy());

说明:

workQueue实现类:

LinkedBlockingQuene不限制大小

ArrayBlockingQuene可控制大小

线程工厂:

Executors.defaultThreadFactory()

处理策略:

ThreadPoolExexutor.AbortPolicy()

可抛出异常。

线程池的注意事项:

1.临时线程什么时候创建?

新任务提交时核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建。

2.什么时候会开始拒绝新任务?

核心线程和临时线程都在忙,任务队列也满了,新的任务过来会拒绝新的任务。

线程池处理Runnable任务

execute()方法:

线程池会自动创建一个线程池,自动执行

\\创建一个Runnable对象

public class MyRunnable implements Runnable{

@Override

public void run(){

System.out.println(Thread.currentThread().getName());

try{

Thread.sleep(1000);

}catch(Exception e){

e.printStackTrace();

}

}

}

```java

public class ThreadPoolTest{

public static void main(String[] args){

new ThreadPoolExecutor(3,5,8,TimeUnit.SECOND,new LinkedBlockingQuene<>(),Executors.defaultThreadFactory(),new ThreadPoolExexutor.AbortPolicy());

Runnable target=new MyRunnable();

pool.execute(target);

//自动创建一个新线程,自动执行

shutdown()

等线程池的任务全部执行完毕,再关闭线程池

pool.shutdown();

shutdownNow()

立即关闭线程池

pool.shutdownNow();

线程池处理Callable方法

Future<> submit()

//定义一个任务类,实现Callable接口

public class MyCallable implement Callable<String>{

private int n;

public MyCallable(int n){

this.n=n;

//重写Callable的call方法

@Override

public String call() throwException{

//描述线程的任务就是返回线程执行返回的结果

int sum=0;

for(int i=0;i<=n;i++){

sum+=i;

return Thread.currentThraed.getName()+sum;

}}

public class ThreadPoolTest{

public static void main(String[] args){

new ThreadPoolExecutor(3,5,8,TimeUnit.SECOND,new LinkedBlockingQuene<>(),Executors.defaultThreadFactory(),new ThreadPoolExexutor.AbortPolicy());

//创建Callable任务

Futuer f1=pool.submit(new MyCallable(100));

//自动创建一个新线程,自动执行

方式二:

使用**Executor(线程池工具类)**调用方法返回不同特点的线程池对象。

public class ThreadPoolTest{

public static void main(String[] args){

//创建固定数量线程的线程池

Executor pool=Executor.newFixedThreadPool(3);

说明:底层还是通过实现类创建的线程池对象

核心线程配置:

计算密集型任务:核心线程数量=CPU的核数+1

IO密集型任务:核心线程数量=CPU的核数×2

**CPU的核数:**ctrl alt delete调出任务管理器,性能中可查

Executors使用可能存在的陷阱

大型并发型系统环境中使用Executors如果不注意可能会出现系统风险。

并发/并行

进程:

正在运行的程序(软件)就是一个独立的进程

线程是属于进程的,一个进程中可以同时运行很多个线程。

进程中的多个线程其实都是并发和并行执行的。

并发的含义:

进程中的线程是由CPU负责调度执行的,到CPU能同时处理线程的数量有限,为了保证全部线程都能往前执行,CPU会为系统的每个线程服务,由于CPU切换的速度很快,给我们的感觉是这些线程在同时执行,这就是并发。

并行的含义

在同一个时刻上,同时有多个线程在被CPU调度执行。

思考:

多线程到底是怎么在执行?

并发和并行同时进行。

线程的生命周期

线程从生到死的过程,经历各种状态和状态转换。

Thread.State();

6种状态

New新建->start()

->Runnable可运行->执行完毕出现异常

->Teminated被终止

Blocked锁堵塞

Waiting无限等待

Timed Waiting计时等待

相关文章