java多线程——线程池

目录

1、什么是线程池?

2、为什么使用线程池?

3、如何使用线程池?


1、什么是线程池?

    线程池是一种线程的使用模式。类似数据库连接池一样,线程可以通过线程池对系统使用的线程进行统一的管理。统一管理线程的创建,调度,销毁等等。

2、为什么使用线程池?

  1. 统一管理。一个功能复杂的系统中,势必需要使用多线程,一旦线程数量过多,就需要统一管理。如果不用线程池进行统一管理,那么就需要浪费大量的经历和无用的重复代码对线程进行管理。
  2. 内存节省。线程其实是系统中的稀缺资源,需要使用线程池对线程使用的内存开销进行管理,减少了每次创建线程、销毁线程的开销。
  3. 提高响应速度。任务提交给线程池之后,就在内部寻找是否有空闲的线程,如果有,则将任务交给某个空闲的线程。由于线程的创建已经完成,故可以直接执行任务,因此提高了响应速度。

3、如何使用线程池?

3.1、创建线程池 -- new ThreadPoolExecutor();

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue)
  • corePoolSize:线程池中常驻的线程数量,即使线程池是空闲的,也会有corePoolSize个线程。
  • maximumPoolSize:线程池中允许的最大线程数。
  • keepAliveTime:空闲线程最大空闲时间。当线程池中的线程超过corePoolSize个线程是,如果线程的空闲时间超过keepAliveTime就会把线程杀死。
  • unit:线程池的时间。
  • BlockingQueue:线程队列。

SynchronousQueue:这个队列接收到任务的时候,会直接提交给线程处理,而不保留它,如果所有线程都在工作怎么办?那就新建一个线程来处理这个任务!所以为了保证不出现<线程数达到了maximumPoolSize而不能新建线程>的错误,使用这个类型队列的时候,maximumPoolSize一般指定成Integer.MAX_VALUE,即无限大
LinkedBlockingQueue:这个队列接收到任务的时候,如果当前线程数小于核心线程数,则新建线程(核心线程)处理任务;如果当前线程数等于核心线程数,则进入队列等待。由于这个队列没有最大值限制,即所有超过核心线程数的任务都将被添加到队列中,这也就导致了maximumPoolSize的设定失效,因为总线程数永远不会超过corePoolSize
ArrayBlockingQueue:可以限定队列的长度,接收到任务的时候,如果没有达到corePoolSize的值,则新建线程(核心线程)执行任务,如果达到了,则入队等候,如果队列已满,则新建线程(非核心线程)执行任务,又如果总线程数到了maximumPoolSize,并且队列也满了,则发生错误
DelayQueue:队列内元素必须实现Delayed接口,这就意味着你传进去的任务必须先实现Delayed接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务
ThreadFactory threadFactory:创建线程的方式,这是一个接口,你new他的时候需要实现他的Thread newThread(Runnable r)方法,
RejectedExecutionHandler handler: 当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理;jdk1.5提供了四种饱和策略 :

AbortPolicy 
默认。直接抛异常。
CallerRunsPolicy 
只用调用者所在的线程执行任务,重试添加当前的任务,它会自动重复调用execute()方法
DiscardOldestPolicy 
丢弃任务队列中最久的任务。
DiscardPolicy 
丢弃当前任务。
 

package com.test;

import java.util.concurrent.*;

public class ThreadTest {


    // 它是一种固定大小的线程池;
    // corePoolSize和maximunPoolSize都为用户设定的线程数量nThreads;
    // keepAliveTime为0,意味着一旦有多余的空闲线程,就会被立即停止掉;但这里keepAliveTime无效;
    // 阻塞队列采用了LinkedBlockingQueue,它是一个无界队列;
    // 由于阻塞队列是一个无界队列,因此永远不可能拒绝任务;
    // 由于采用了无界队列,实际线程数量将永远维持在nThreads,因此maximumPoolSize和keepAliveTime将无效。
    public static ExecutorService newFixedThreadPool(int nThreads) {

        return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

    }

    // 它是一个可以无限扩大的线程池;
    // 它比较适合处理执行时间比较小的任务;
    // corePoolSize为0,maximumPoolSize为无限大,意味着线程数量可以无限大;
    // keepAliveTime为60S,意味着线程空闲时间超过60S就会被杀死;
    // 采用SynchronousQueue装等待的任务,这个阻塞队列没有存储空间,这意味着只要有请求到来,就必须要找到一条工作线程处理他,如果当前没有空闲的线程,那么就会再创建一条新的线程。

    public static ExecutorService newCachedThreadPool(){
        return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.MILLISECONDS,new SynchronousQueue<Runnable>());
    }

    //它只会创建一条工作线程处理任务;
    //采用的阻塞队列为LinkedBlockingQueue;
    public static ExecutorService newSingleThreadExecutor(){
        return new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
    }


}

3.2、向线程池提交任务

public static void main(String[] args) {
        Executor executor = ThreadTest.newCachedThreadPool();
        executor.execute(new Runnable() {
            int i = 0;
            @Override
            public void run() {
                System.out.println(i++);
            }
        });

    }

3.3线程池关闭

 看了一下源码executor没有shutdown方式,需要转成ExecutorService。

void shutdown():不会立即终止线程池,首先将线程池的状态设置成STOP,然后尝试停止所有的正在执行或暂停任务的线程。此时,则不能再往线程池中添加任何新的任务,否则将会抛出RejectedExecutionException异常。但是,此时线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。

List<Runnable> shutdownNow():将线程池的状态设置成SHUTDOWN状态,立即终止线程池,并且尝试打断正在运行的线程,清空缓存队列中的任务,返回尚未开始的任务。

它们的原理是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以无法响应中断的任务可能永远无法终止。只要调用了这两个关闭方法中的任意一个,isShutdown方法就会返回true。当所有的任务都已关闭后,才表示线程池关闭成功,这时调用isTerminaed方法会返回true。至于应该调用哪一种方法来关闭线程池,应该由提交到线程池的任务特性决定,通常调用shutdown方法来关闭线程池,如果任务不一定要执行完,则可以调用shutdownNow方法。

((ExecutorService) executor).shutdown();

 

更多内容请关注微信公众号“外里科技

官方公众号外里科技
运营公众号英雄赚
微信wxid_8awklmbh1fzm22
QQ1247408032
开源代码https://gitee.com/B_T/beimi

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值