java线程池学习

      • java中ThreadPoolExecutor类
          • Executor 接口
          • ExecutorService 接口
          • AbstractExecutorService 抽象类
          • ThreadPoolExecutor核心类
          • workQueue
          • threadFactory 线程工厂
          • handler
      • 深入剖析线程池实现原理
          • 线程池状态
          • 任务的执行
          • 线程池中的线程初始化
          • 任务缓存队列及排列策略
          • 任务拒绝策略
          • 线程池的关闭
          • 线程池容量的动态调整
      • java线程池的使用
          • newCachedThreadPool
          • newFixedThreadPool
          • newScheduledThreadPool
          • newSingleThreadExecutor

java中ThreadPoolExecutor类

Executor 接口

只声明一个方法execute(Runnable) 返回值为void 参数为Runnable类型 用来执行传递进去的任务

ExecutorService 接口

继承Executor接口 并额外声明一些方法:submit() invokeAll() invokeAny()以及shutDown()等

AbstractExecutorService 抽象类

实现了ExecutorService接口 基本实现了ExecutorService中声明的所有方法

ThreadPoolExecutor(核心类)

继承了AbstractExecutorService类 重要的方法 execute() submit() shutdown() shutdownNow()

execute() 在ThreadPoolExecutor中进行了具体的实现,这个方法是ThreadPoolExecutor的核心方法 通过这个方法向线程池提交一个任务 交由线程池执行

submit() 是在ExecutorService中声明的方法 在AbstractExecutorService就已经有了具体的实现 在ThreadPoolExecutor中并没有对其进行重写 这个方法也是用来
    向线程池提交任务的 但是它和execute()方法不同 它能返回任务执行结果 submit()方法的实现实际上还是调用的execute()方法 只不过它利用了Future来获取任务执行结果

shutdown()和shutdownNow()是用来关闭线程的

还有其他的方法 getQueue() getPoolSize() getActiveCount() getCompletedTaskCount()等获取与线程池相关属性的方法
workQueue

阻塞对列 线程池的排队策略与BlockingQueue有关
ArrayBlockingQueue
PriorityBlockingQueue
LinkedBlockingQueue
SynchronousQueue

threadFactory 线程工厂

主要用来创建线程

handler

表示当拒绝处理任务时的策略
ThreadPoolExecutor.AbortPolicy 丢弃任务并抛出RejectedExecutionException异常
ThreadPoolExecutor.DiscardPolicy 也是丢弃任务 但是不抛出异常
ThreadPoolExecutor.DiscardOldestPolicy 丢弃队列最前面的任务 然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy 由调用线程处理该任务

深入剖析线程池实现原理

线程池状态
使用volatile变量用来保证线程之间的可见性

RUNNING状态 创建线程池后 初始化 线程池处于RUNNING状态

调用shutdown时 此时线程池处于SHUTDOWN状态 线程池此时不能接受新的任务 它会等待所有的任务执行完毕

调用shutdownNow时 此时线程池处于STOP状态 此时线程时不能接受新的任务 并且会去尝试终止正在执行的任务

当线程池处于SHUTDOWN或STOP状态,并且所有工作线程已经销毁 任务缓存队列已经清空或执行结束后 线程池被设置为TERMINATED状态
任务的执行
如果当前线程池中的线程数目小于corePoolSize 则每来一个任务 就会创建一个线程取执行

如果当前线程池中的线程数目大于等于corePoolSize 则每来一个任务 会尝试将其添加到任务缓存队列中 若添加成功 则该任务会等待空闲进程会将其取出执行 若添加失败
    (一般来说就是任务缓存队列已满) 则会尝试创建新的线程去执行任务

如果当前线程池中的线程数目达到maximumPoolSize 则会采取任务拒绝策略进行处理

如果当前线程池中的线程数目大于corePoolSize 如果某线程空闲时间超过keepAliveTime 线程将被终止 直到线程池中的线程数目不大于corePoolSize 如果允许为核心
    池中的线程设置存活时间 那么核心池中的线程空闲时间超过keepAliveTime 线程也会被终止
线程池中的线程初始化
默认情况下 创建线程池后 线程池中是没有线程的 需要提交任务后才会创建线程

实际中如果需要线程池创建之后立即创建线程 可以如下
    prestartCoreThread() 初始化一个核心线程

    prestarAllCoreThreads() 初始化所有核心线程
任务缓存队列及排列策略
workQueue 阻塞对列 用来存放等待执行的任务 类型为BlockingQueue<Runnable>

    ArrayBlockingQueue 基于数组的先进先出队列 此队列创建时必须指定大小

    LinkedBlockingQueue 基于链表的先进先出队列 如果创建时没有指定此队列大小 则默认为Integer.MAX_VALUE

    SynchronousQueue 它不会保存提交的任务 而是直接新建一个线程来执行新来的任务
任务拒绝策略
当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize 如果还有任务到来就会采取任务拒绝策略 即上面提到的4种策略
线程池的关闭
ThreadPoolExecutor提供了2种方法 shutdown与shutdownNow,前者不会立即终止线程池 而要等所有任务缓存队列中的任务都执行完后才终
    止 但再也不会接受新的任务 后者立即终止线程池 并且尝试打断正在执行的任务 并且清空任务缓存队列 返回尚未执行的任务
线程池容量的动态调整
ThreadPoolExecutor提供了动态调整线程池容量的方法 setCorePoolSize()和setMaximumPoolSize()

setCorePoolSize 设置核心池大小

setMaximumPoolSize 设置线程池最大能创建的线程数目大小

java线程池的使用

Java 通过Executors提供四种线程池

  • newCachedThreadPool 可缓存线程池,如果线程池长度超过处理需要,可灵活的回收空闲线程,若无可回收,则创建新线程。

  • newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

  • newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

  • newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO,优先级)执行。

    newCachedThreadPool

    创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活的回收空闲线程,若无可回收,则创建新线程。


package com.frankstar;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/** * @author frankstar * @function newCachedThreadPool 创建一个可缓存的线程池 */
public class ThreadPoolExecutorsTest {

    public static void main(String[] args) {
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int index = 1;
            try {
                Thread.sleep(index * 1000);
            } catch (InterruptedException e){
                e.printStackTrace();
            }
            cachedThreadPool.execute(new Runnable() {
                public void run() {
                    System.out.println(index);
                }
            });
        }
    }

}
newFixedThreadPool

创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待

package com.frankstar;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/** * @author frankstar * @function newCachedThreadPool 创建一个定长的线程池 */
public class ThreadPoolExecutorsTest {
  ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            final int index = 1;
            fixedThreadPool.execute(new Runnable() {
                public void run() {
                    try {
                        System.out.println(index);
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

线程池大小设置为3,每个任务输出index后sleep2秒,所以每两秒打印3个数字

newScheduledThreadPool

创建一个定长线程池,支持定时周期性任务执行

public void scheduledThreadTest() {
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            public void run() {
                //表示延迟1秒后每3秒执行一次
                System.out.println("delay 1 second, and execute every 3 seconds");
            }
        }, 1, 3, TimeUnit.SECONDS);
    }

表示延迟1秒后每3秒执行一次

newSingleThreadExecutor

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行

public void singledThreadTest() {
        ExecutorService singledThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            final int index = 1;
            singledThreadExecutor.execute(new Runnable() {
                public void run() {
                    try {
                        System.out.println(index);
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

结果依次输出,相当于顺序执行各个任务

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