创建线程的四大方法及线程池的七大参数

为什么要使用线程池?

线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后再线程创建后启动这些任务如果线程的数量超过最大数量,超过数量的线程将排队等候,等其他线程执行完毕,再从队列中取出任务来执行

特点:线程复用,控制最大并发数,管理线程

一、降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁造成的消耗

二、提高响应速度,当任务到达时,任务可以不需要的等到线程创建就能够立刻执行

三、提高线程的可管理性,线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,

还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

创建线程的前两种方法:继承Thread类,实现Runnable接口
创建线程的第三种方法:使用Callable创建线程

public class Test {
    public static void main(String[] args) throws Exception{
        FutureTask<Integer> futureTask = new FutureTask<>(new Thre());
        Thread thread = new Thread(futureTask,"AAA");
        thread.start();
        while (!futureTask.isDone()){

        }

        System.out.println(futureTask.get());
    }

}

class Thre implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("哈哈哈");
        return 1024;
    }
}

创建线程的第四种方法(企业常用):使用线程池创建线程

 public static void main(String[] args){
        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        //ExecutorService executorService = Executors.newSingleThreadExecutor();
        //ExecutorService executorService1 = Executors.newCachedThreadPool();
        //模拟10个用户办理业务,
        try {
            for (int i = 0; i < 20; i++) {
                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"办理业务");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }

    }

下面分析一下  

(1)Executors.newFixedThreaPool(5);

源码:

   public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

 

(2)Executors.newSingleThreadExecutor()

源码:

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

 

(3)Executors.newCachedThreadPool();

源码:

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

上述线程池创建时底层都是五个参数,接着往下看ThreafPoolExecutor源码:

  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

我们发现,它调用了一个this方法,即它的构造函数,是传的7个参数,点进this方法,源码:

public ThreadPoolExecutor(int corePoolSize,                      //1
                              int maximumPoolSize,               //2
                              long keepAliveTime,                //3
                              TimeUnit unit,                     //4
                              BlockingQueue<Runnable> workQueue, //5
                              ThreadFactory threadFactory,       //6
                              RejectedExecutionHandler handler) { //7
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

我们可以清楚的看到,传的是7个参数。下面详细讲解这七大参数:

1.corePoolSize:线程池中的常驻核心线程数

在创建了线程池后,当有请求任务进来之后,就会安排池中的线程去执行请求任务,近似理解为今日当值线程

当线程池中的线程数目达到corePoolSize后,就会把到达的任务放入缓存队列中。

2.maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1

3.keepAliveTime:多余的空闲线程的存活时间。

当前线程池数量超过corePoolSize时,当空闲时间达到keepAliveTime值时,

多余空闲线程会被销毁直到只剩下corePoolSize个线程为止

默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池找那个的线程数不大于corePoolSize。

4.unit:keepAliveTime的单位

5.workQueue:任务队列,被提交但尚未被执行的任务

6.threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程一般默认即可

7.handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池最大线程数(maximumPoolSize)时如何处理

 

以上可对比银行网点的办理模式,在这就不详细说了哦,想通了也就完全理解了!!!

 

  • 8
    点赞
  • 112
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
线程池是Java中用于管理和复用线程的机制,它可以提高线程的利用率和性能。线程池七大参数包括: 1. corePoolSize(核心线程数):线程池中始终保持的线程数量,即使它们处于空闲状态。当任务数量超过核心线程数时,线程池创建新的线程来处理任务。 2. maximumPoolSize(最大线程数):线程池中允许存在的最大线程数量。当任务数量超过最大线程数时,新的任务会被放入等待队列中等待执行。 3. keepAliveTime(线程空闲时间):当线程池中的线程数量超过核心线程数时,多余的空闲线程在等待新任务到来时的最长等待时间。超过这个时间,空闲线程会被销毁。 4. unit(时间单位):用于设置keepAliveTime的时间单位,可以是秒、毫秒、分钟等。 5. workQueue(任务队列):用于存放等待执行的任务的队列。常见的队列类型有有界队列(如ArrayBlockingQueue)和无界队列(如LinkedBlockingQueue)。 6. threadFactory(线程工厂):用于创建线程的工厂类。可以自定义线程的名称、优先级等属性。 7. handler(拒绝策略):当任务无法被线程池执行时的处理策略。常见的策略有直接抛出异常、丢弃任务、丢弃队列中最旧的任务等。 线程池的作用主要有以下几点: 1. 提高性能:线程池可以复用线程,避免了频繁创建和销毁线程的开销,提高了系统的性能。 2. 控制资源:通过设置核心线程数和最大线程数,可以控制系统中并发线程的数量,避免资源被过度占用。 3. 提供任务队列:线程池可以提供一个任务队列,用于存放等待执行的任务。当线程池中的线程都在执行任务时,新的任务会被放入队列中等待执行。 4. 管理线程线程池可以统一管理线程的生命周期,包括创建、销毁、空闲时间等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值