JAVA-线程池篇

线程的劣势:

1、线程创建的数量是不可控的

2、频繁创建和销毁线程

线程池的优势:

1、控制线程的数量

2、降低频繁创建和销毁线程

3、对于任务的响应速度更快

java中提供的线程池

jdk中的Executors

Execitors.newFixedThreadPool(3);固定线程

Executors.newSingThreadExecutor();只有一个核心线程的线程池

Executors.newCachedThreadPool();伸缩性60秒回收

Executors.newScheduleThreadPool();定时任务

线程池的优点:

    1、线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用

    2、可以根据系统的承受能力,调整线程池中工作线程的熟练,防止因为消耗过多内存导致服务器崩溃

线程池的创建:

参数详解

corePoolSize:线程池核心线程数量。创建线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务,除非预创建线程,调用prestartAllCoreThreads(),在任务到来之前就创建corePoolSize个线程。当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列中

maximumPoolSize:线程池能创建线程的最大个数。如果阻塞队列已满,并且当前线程池线程个数没有超过maxnumPoolSize,就会创建新的线程来执行任务。

 keepAliveTime:当活跃线程数大于核心线程数时,并且线程空闲时间超过了keepAliveTime,就会将这些空闲线程销毁,尽可能降低系统资源损耗;只有当线程中的线程数大于corePoolSize时才其作用

unit:存活时间的单位,在TimeUnit类中有7种静态属性

workQueue:存放任务的队列,一个阻塞队列,用来存储等待执行的任务

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

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

       synchronousQueue:不会保存提交的任务,而是将直接创建一个线程来执行任务

threadFactory:创建线程的工厂类,可以通过指定线程工厂为每个创建出来的线程设置更有意义的名字

handler:超出线程范围和队列容量的任务的处理程序,需要一种策略处理这种情况

         AbortPolicy:直接拒绝所提交的任务,提交异常

         CallerRunsPolicy:只用调用者所在的线程来执行任务

          DiscardPolicy:不处理直接丢弃掉任务

          DiscardOldPolicy:丢弃掉阻塞队列中存放时间最久的任务,执行当前的任务

线程池实现原理

JAVA-线程池篇_第1张图片

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    //如果线程池的线程个数小于corePoolSize则创建新线程执行当前任务
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    //如果线程个数大于corePoolSize或者创建线程失败,则将任务存储到阻塞队列中
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        if (! isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    //如果当前任务无法放进阻塞队列中,则创建新的线程来执行任务,否则执行拒绝策略
    else if (!addWorker(command, false))
        reject(command);
}

取得当前线程数与线程池corePoolSize比较,如果时小于,将通过addWorker()方法调度执行,直接创建一个线程并且执行

如果大于的话,那么提交到等待队列中

如果进入等待队列失败,则会将任务直接提交给线程池

如果线程数达到最大线程数,那么就提交失败,执行拒绝策略

线程池的关闭
关闭线程池,可以通过shutdown和shutdownNow俩个方法,原理是遍历线程池中所有的线程,然后依次中断线程

shutdownNow:将线程池的状态设置为STOP,然后尝试停止所有正在执行和未执行任务的线程,并返回等待执行任务的列表

shutdown:只是将线程池的状态设置为SHUTDOWN,然后中断所有没有正在执行任务的线程

demo案列:

/**
 * @program: threadpool
 * @author: xuWei
 * @create: 2019/03/19
 * @description: 线程池实现类
 */
public class TestPool {

    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue(5));

        for(int i=0;i<15;i++){
            MyTask myTask = new MyTask(i);
            executor.execute(myTask);
            System.out.println("线程池中线程数目:"+executor.getPoolSize()+",队列中等待执行的任务数目:"+
                    executor.getQueue().size()+",已执行玩别的任务数目:"+executor.getCompletedTaskCount());
        }
        executor.shutdown();
    }
}

class MyTask implements Runnable {
    private int taskNum;

    public MyTask(int num) {
        this.taskNum = num;
    }

    @Override
    public void run() {
        System.out.println("正在执行task "+taskNum);
        try {
            Thread.currentThread().sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("task "+taskNum+"执行完毕");
    }
}

返回结果:

JAVA-线程池篇_第2张图片

手写一个简便的线程池

/**
 * @author: xuWei
 * @create: 2019/12/11
 */
public interface IThreadPool {

    /**
     * @Author : xuwei
     * @Date : 2019-08-21  11:34
     * @Description :  加入任务
     * @Param : [task]
     * @Return : void
     */
    void execute(Runnable task);

    /**
     * @Author : xuwei
     * @Date : 2019-08-21  11:34
     * @Description :  加入任务
     * @Param : [task]
     * @Return : void
     */
    void execute(Runnable[] tasks);

    /**
     * @Author : xuwei
     * @Date : 2019-08-21  11:34
     * @Description :  加入任务
     * @Param : [task]
     * @Return : void
     */
    void execute(List tasks);

    /**
     * @Author : xuwei
     * @Date : 2019-08-21  11:34
     * @Description :  销毁线程
     * @Param : [task]
     * @Return : void
     */
    void destroy();

 线程池实现类:

/**
 * @program: demo
 * @author: xuWei
 * @create: 2019/12/11
 * @description: 手写一个线程池
 */
public class MyThreadPool implements IThreadPool {

    static int work_number = 5;

    static volatile int sumCount = 0;

    static List taskQueue = new LinkedList();

    WorkerThread[] workerThreads;

    static AtomicLong threadNum=new AtomicLong();

    static MyThreadPool myThreadPool;

    public MyThreadPool(){
        this(work_number);
    }

    public MyThreadPool(int workNum){
        MyThreadPool.work_number=workNum;

        //开辟工作线程空间
        workerThreads = new WorkerThread[work_number];

        //开始创建工作线程
        for(int i=0;i tasks) {
        synchronized (taskQueue) {
            for (Runnable task : tasks) {
                taskQueue.add(task);
            }
            taskQueue.notifyAll();
        }
    }

    @Override
    public void destroy() {
        //循环是否还存在任务,如果存在等待20毫秒处理时间
        while (!taskQueue.isEmpty()) {
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果任务队列已处理完成,销毁线程,清空任务
        for (int i = 0; i < work_number; i++) {
            workerThreads[i].setWorkerFlag();
            workerThreads[i] = null;
        }
        myThreadPool = null;
        taskQueue.clear();
    }


    /**
     * 创建工作线程池
     */
    class WorkerThread extends Thread {
        /**
         * 用来标识当前线程属于活动可用状态
         */
        private boolean isRunning = true;

        @Override
        public void run() {
            Runnable runnable = null;
            //死循环
            while (isRunning) {
                //非线程安全,所以采用同步锁
                synchronized (taskQueue) {
                    while (isRunning && taskQueue.isEmpty()) {
                        try {
                            //如果任务队列为空,等待20毫秒 监听任务到达
                            taskQueue.wait(20);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    //任务队列不为空
                    if (!taskQueue.isEmpty()) {
                        //获取第一个任务
                        runnable = taskQueue.remove(0);
                    }
                }
                if (runnable != null) {
                    runnable.run();
                }
                sumCount++;
                runnable = null;
            }
        }

        /**
         * 销毁线程
         */
        public void setWorkerFlag() {
            isRunning = false;
        }
    }
}

测试类:

/**
 * @program: demo
 * @author: xuWei
 * @create: 2019/12/11
 * @description:
 */
public class MyThreadPoolTest {

    public static void main(String[] args) {
        //获取线程池
        IThreadPool t = MyThreadPool.getThreadPool(20);

        List taskList = new ArrayList();
        for (int i = 0; i < 100; i++) {
            taskList.add(new Task());
        }
        //执行任务
        t.execute(taskList);
        System.out.println(t);
        //销毁线程
        t.destroy();
        System.out.println(t);
    }

    static class Task implements Runnable {

        private static volatile int i = 1;

        @Override
        public void run() {
            System.out.println("当前处理的线程:" + Thread.currentThread().getName() + " 执行任务" + (i++) + " 完成");
        }
    }
}

效果显示

JAVA-线程池篇_第3张图片

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