ThreadPoolExcutor

ThreadPoolExcutor_第1张图片
ThreadPoolExcutor_第2张图片

2、线程池的创建

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)

 corePoolSize:      线程池维护线程的最少数量 (core : 核心)
核心池的大小,默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,
就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达
的任务放到缓存队列当中。
 maximumPoolSize:   线程池维护线程的最大数量 
 keepAliveTime:     线程池维护线程所允许的空闲时间
表示线程没有任务执行时最多保持多久时间会终止。 注意  默认情况下,只有当线程池中的
线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于
corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间
达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。
 unit:               线程池维护线程所允许的空闲时间的单位
 workQueue:          线程池所使用的缓冲队列
 handler:            线程池对拒绝任务的处理策略

3、ThreadPoolExcutor内部执行流程

当一个任务通过execute(Runnable)方法欲添加到线程池时:

如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。

如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。

如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。

如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。

也就是:处理任务的优先级为:

核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。

当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

unit可选的参数为java.util.concurrent.TimeUnit中的几个静态属性:NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。

 workQueue常用的是:java.util.concurrent.ArrayBlockingQueue
 handler有四个选择:
      ThreadPoolExecutor.AbortPolicy():     抛出java.util.concurrent.RejectedExecutionException异常
      ThreadPoolExecutor.CallerRunsPolicy():     重试添加当前的任务,他会自动重复调用execute()方法

      ThreadPoolExecutor.DiscardOldestPolicy():     抛弃旧的任务

      ThreadPoolExecutor.DiscardPolicy():     抛弃当前的任务

线程池的创建

1》创建固定个数的线程池

ExecutorService  es = Exectors.newFixedThreadPool(10);

2》创建带缓存的线程池

ExecutorService es = Executors.newCachedThreadPool();
使用场景:短期有大量任务

3》创建可以执行定时任务的线程池

//创建执行定时任务的线程池
ScheduleExecutorService ses = Executors.newScheduledThreadPool(2);
//执行定时任务
ses.scheduledAtFixdRate(new Runnable(){
  Public void run(){
}
},1,3,TimeUnit.SECONDS);

ses.schedule()只会执行一次
ses.scheduleWithFixedDelay() VS ses.scheduledAtFixdRate()
前者:以上一次任务的结束时间作为下一次任务的开始时间
后者:以上一次的开始时间作为下一次任务开始的时间

4》创建单线程执行定时任务的线程池

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();

5》创建单个线程池

ExecutorService es = Executors.newSingleThreadExector();

创建单个线程池有什么用?

1)可以避免频发的创建线程和销毁线程带来的开销,
2)有任务队列可以存储多余的任务
3)当有大量的任务不能处理的时候,可以友好的执行拒绝策略
4)可以更好地管理任务

6》原始的线程池创建方式

ThreadPoolExecutor
ThreadPoolExecutor tpe =new ThreadPoolExecutor(
核心线程数(线程正常情况下),
最大线程数量(当有大量任务的时候可以创建的最多的线程数),
最大线程存活时间,
单位时间,
任务队列,
线程工厂,
拒绝策略);

核心线程数小于等于最大线程数;
当任务量小于核心线程数时,就会创建一个线程来执行此任务,
当任务量大于等于核心线程数时会先把任务放到任务队列里,当任务队列放满时,再创建线程(最大线程数),如果最大线程也使用完,就执行拒绝策略。

拒绝策略:

> 1)默认拒绝,不执行任务抛出异常:ThreadPoolExecutor.AbortPolicy();
> 2)把当前任务交给主线程执行:ThreadPoolExecutor.CallerRunsPolicy();
> 3)丢弃最老的任务:ThreadPoolExecutor.DiscardOldestPolicy();
> 4)丢弃最新的任务:ThreadPoolExecutor.DiscardPolicy();

线程池使用:

1)execute(Runnable m没有返回值)
2)submit(Runnable/Callable 有返回值,返回值使用Future接收)

线程池终止

 shutdown(); //结束线程池
shutdown();//立即结束线程池

线程缺点:

1)线程的创建会开辟本地方法栈,虚拟机栈,程序计数器变成线程私有的内存,同时消耗的时候需要销毁以上三个区域,因此频繁的创建和消耗比较消耗系统资源
2)在任务量远远大于线程可以处理的任务量时,并不能有好的拒绝任务。

线程池优点:

1)可以避免频繁的创建和消耗线程。
2)可以更好地管理线程的个数和资源的个数
3)拥有更多的功能,比如线程池可以进行定时任务的执行
4)线程池可以更优化的拒接不能处理的任务

Java里创建线程主要有三种方式:

继承 Thread类:Thread 类本质上是实现了 Runnable 接口的一个实例,代表一个线程的实例。启动线程的唯一方法就是通过Thread 类的 start()实例方法。start()方法是一个 native 方法,它将启动一个新线程,并执行 run()方法。

实现 Runnable接口:如果自己的类已经 extends 另一个类,就无法直接 extends Thread,此时,可以实现一个Runnable 接口。

实现 Callable接口:实现Callable接口,重写call()方法,可以返回一个 Future类型的返回值。我在上面的例子里就是用到了这种方式。

说说线程的生命周期和状态

1.new初始状态
2.runnable 运行状态
3.blocked 阻塞状态
4.waiting 等待状态
5.time_waiting :超时等待状态
6.terminated:终止状态

产生死锁必须满足四个条件:

互斥条件:该资源任意⼀个时刻只由⼀个线程占⽤。
请求与保持条件:⼀个进程因请求资源⽽阻塞时,对已获得的资源保持不放。
不剥夺条件:线程已获得的资源在末使⽤完之前不能被其他线程强⾏剥夺,只有⾃⼰使⽤完毕后才释放资源。
循环等待条件:若⼲进程之间形成⼀种头尾相接的循环等待资源关系。

你可能感兴趣的:(java,线程,线程池)