java的线程池原理是什么

发布时间:2021-10-21 10:53:04 作者:柒染
来源:亿速云 阅读:150

这篇文章将为大家详细讲解有关java的线程池原理是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

    在之前已经使用过线程池了。在使用中,基本上就是初始化好线程池的实例之后,把任务丢进去,等待调度执行就可以了。使用起来非常简单方便。

new Thread弊端

线程池的好处

ThreadPoolExecutor

参数:

    如果运行的线程数小于CorePoolSize时,直接创建新线程创建任务,即使线程池中的其他线程是空闲的。

    如果线程池中的线程数量大于等于CorePoolSize且小于maximumPoolSize时,则只有当wokQueue满时才创建新的线程去处理任务。

    如果我们设置CorePoolSize与maximumPoolSize相等,那么创建的线程池大小是固定的,这时如果有新任务提交且workQueue还没满,就把请求放入workQueue中,等待空闲线程从workQueue中取任务进行处理。

    如果运行的线程数量大于maximumPoolSize时,这时如果workQueue满,那么会通过一个拒绝策略参数来指定策略处理任务。

    如果我们想降低系统资源的消耗,包括CPU的使用率、操作系统资源的消耗,可以设置一个较大的workQueue容量和较小的CorePoolSize容量,这样会降低线程处理的吞吐量。如果我们提交的任务经常发生阻塞,我们可以设置maximumPoolSize来设置线程池容量。如果我们队列容量较小,通常需要把maximumPoolSize设置大一些,这样CPU使用率会高一些。但是如果线程池容量设置过大,在提交人物数量过多的情况下,并发量会增加,那么线程间资源调度就是一个需要考虑的问题,反而会降低处理的吞吐量。

线程池状态

java的线程池原理是什么

当我们初始化一个线程池之后,通常有上面几种状态。

running:可以接受新提交的任务,也能处理阻塞队列中的任务。

shutdown:关闭状态,当一个线程池实例处于shutdown状态时,不能再接收新提交的任务,但却可以继续处理阻塞队列中已经保存的任务。

stop:也不能接收新的任务,也不处理队列中的任务。会中断正在处理的线程任务。

tidying:所有任务都已经终止了,没有活动中的线程。当线程池进行该状态时候,会执行钩子方法terminated() 。

ThreadPoolExecutor中的方法

  1. execute():提交任务,交给线程池执行

  2. submit():提交任务,能够返回执行结果 相当于execute+Future

  3. shutdown():关闭线程池,等待任务都执行完

  4. shutdownNow():关闭线程池,不等待任务执行完

  5. getTaskCount():线程池已执行和未执行的任务总数

  6. getCompletedTaskCount():已完成的任务数量

  7. getPoolSize():线程池当前的线程数量

  8. getActiveCount():当前线程池中正在执行任务的线程数量

java的线程池原理是什么

Executors框架接口

 Executors.newCachedThreadPool示例代码:

@Slf4j
public class ThreadPoolExample1 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i< 10; i++){
            final int index = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    log.info("task:{}", index);
                }
            });
        }
        //一定要关闭线程池,否则程序不结束
        executorService.shutdown();
    }
}

Executors.newSingleThreadExecutor示例代码:

@Slf4j
public class ThreadPoolExample3 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i< 10; i++){
            final int index = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    log.info("task:{}", index);
                }
            });
        }
        //一定要关闭线程池,否则程序不结束
        executorService.shutdown();
    }
}

输出结果:

17:08:16.870 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:0
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:1
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:2
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:3
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:4
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:5
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:6
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:7
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:8
17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:9

相当于单线程按顺序执行。  

Executors.newScheduledThreadPool代码示例:

@Slf4j
public class ThreadPoolExample4 {
    public static void main(String[] args) {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                log.warn("schedule run");
            }
        },1, 3, TimeUnit.SECONDS);
        //这里不需要关闭线程池
        //scheduledExecutorService.shutdown();
    }
}

上面目的是:延迟1秒后,每个三秒执行一次任务,由于这个任务时不定的执行,因此这里不应该关闭线程池。如果需要关闭线程池的话,可以设置一个触发条件来关闭。类似于Timer类:

@Slf4j
public class ThreadPoolExample4 {
    public static void main(String[] args) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                log.warn("timer run");
            }
        }, new Date(), 5*1000);
    }
}

线程池合理配置

    我们只用线程池主要是为了重用存在的线程,减少对象创建消亡,能有效控制最大线程并发数,可以避免过多的资源竞争和阻塞,也可以定时执行单线程与控制线程的执行性能比较好。 这不代表线程池应该随时随地用,一定要根据自己的实际场景来分析使用参数配置

关于java的线程池原理是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

推荐阅读:
  1. java中自定义线程池的原理是什么
  2. Java中线程池的执行原理是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:如何理解加密算法RSA

下一篇:Unity NGUI如何实现移动端输入法取认事件响应

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》