一、如下方式存在的问题

new Thread() {    @Override    public void run() {        // 业务逻辑    }}.start();

1、首先频繁的创建、销毁对象是一个很消耗性能的事情;2、如果用户量比较大,导致占用过多的资源,可能会导致我们的服务由于资源不足而宕机;3、综上所述,在实际的开发中,这种操作其实是不可取的一种方式。

二、使用线程池有什么优点

1、线程池中线程的使用率提升,减少对象的创建、销毁;2、线程池可以控制线程数,有效的提升服务器的使用资源,避免由于资源不足而发生宕机等问题;

三、线程池的四种使用方式

1、newCachedThreadPool

创建一个线程池,如果线程池中的线程数量过大,它可以有效的回收多余的线程,如果线程数不足,那么它可以创建新的线程。

public static void method() throws Exception {    ExecutorService executor = Executors.newCachedThreadPool();    for (int i = 0; i < 5; i++) {        final int index = i;        Thread.sleep(1000);        executor.execute(new Runnable() {            @Override            public void run() {                System.out.println(Thread.currentThread().getName() + "  " + index);            }        });    }}

执行结果

通过分析我看可以看到,至始至终都由一个线程执行,实现了线程的复用,并没有创建多余的线程。如果当我们的业务需要一定的时间进行处理,那么将会出现什么结果。我们来模拟一下。

可以明显的看出,现在就需要几条线程来交替执行。

不足:这种方式虽然可以根据业务场景自动的扩展线程数来处理我们的业务,但是最多需要多少个线程同时处理缺是我们无法控制的;

优点:如果当第二个任务开始,第一个任务已经执行结束,那么第二个任务会复用第一个任务创建的线程,并不会重新创建新的线程,提高了线程的复用率;

2、newFixedThreadPool

这种方式可以指定线程池中的线程数。举个栗子,如果一间澡堂子最大只能容纳20个人同时洗澡,那么后面来的人只能在外面排队等待。如果硬往里冲,那么只会出现一种情景,摩擦摩擦...

首先测试一下最大容量为一个线程,那么会不会是我们预测的结果。

public static void method_01() throws InterruptedException {    ExecutorService executor = Executors.newFixedThreadPool(1);    for (int i = 0; i < 10; i++) {        Thread.sleep(1000);        final int index = i;        executor.execute(() -> {            try {                Thread.sleep(2 * 1000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(Thread.currentThread().getName() + "  " + index);        });    }    executor.shutdown();}

执行结果

我们改为3条线程再来看下结果

优点:两个结果综合说明,newFixedThreadPool的线程数是可以进行控制的,因此我们可以通过控制最大线程来使我们的服务器打到最大的使用率,同事又可以保证及时流量突然增大也不会占用服务器过多的资源。

3、newScheduledThreadPool

该线程池支持定时,以及周期性的任务执行,我们可以延迟任务的执行时间,也可以设置一个周期性的时间让任务重复执行。 该线程池中有以下两种延迟的方法。

  • scheduleAtFixedRate

测试一

public static void method_02() {    ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);    executor.scheduleAtFixedRate(new Runnable() {        @Override        public void run() {            long start = new Date().getTime();            System.out.println("scheduleAtFixedRate 开始执行时间:" +                    DateFormat.getTimeInstance().format(new Date()));            try {                Thread.sleep(5000);            } catch (InterruptedException e) {                e.printStackTrace();            }            long end = new Date().getTime();            System.out.println("scheduleAtFixedRate 执行花费时间=" + (end - start) / 1000 + "m");            System.out.println("scheduleAtFixedRate 执行完成时间:" + DateFormat.getTimeInstance().format(new Date()));            System.out.println("======================================");        }    }, 1, 5, TimeUnit.SECONDS);}

执行结果

测试二

总结:以上两种方式不同的地方是任务的执行时间,如果间隔时间大于任务的执行时间,任务不受执行时间的影响。如果间隔时间小于任务的执行时间,那么任务执行结束之后,会立马执行,至此间隔时间就会被打乱。

  • scheduleWithFixedDelay

测试一

public static void method_03() {    ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);    executor.scheduleWithFixedDelay(new Runnable() {        @Override        public void run() {            long start = new Date().getTime();            System.out.println("scheduleWithFixedDelay 开始执行时间:" +                    DateFormat.getTimeInstance().format(new Date()));            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }            long end = new Date().getTime();            System.out.println("scheduleWithFixedDelay执行花费时间=" + (end - start) / 1000 + "m");            System.out.println("scheduleWithFixedDelay执行完成时间:"                    + DateFormat.getTimeInstance().format(new Date()));            System.out.println("======================================");        }    }, 1, 2, TimeUnit.SECONDS);}

执行结果

测试二

public static void method_03() {    ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);    executor.scheduleWithFixedDelay(new Runnable() {        @Override        public void run() {            long start = new Date().getTime();            System.out.println("scheduleWithFixedDelay 开始执行时间:" +                    DateFormat.getTimeInstance().format(new Date()));            try {                Thread.sleep(5000);            } catch (InterruptedException e) {                e.printStackTrace();            }            long end = new Date().getTime();            System.out.println("scheduleWithFixedDelay执行花费时间=" + (end - start) / 1000 + "m");            System.out.println("scheduleWithFixedDelay执行完成时间:"                    + DateFormat.getTimeInstance().format(new Date()));            System.out.println("======================================");        }    }, 1, 2, TimeUnit.SECONDS);}

执行结果

总结:同样的,跟scheduleWithFixedDelay测试方法一样,可以测出scheduleWithFixedDelay的间隔时间不会受任务执行时间长短的影响。

4、newSingleThreadExecutor

这是一个单线程池,至始至终都由一个线程来执行。

public static void method_04() {    ExecutorService executor = Executors.newSingleThreadExecutor();    for (int i = 0; i < 5; i++) {        final int index = i;        executor.execute(() -> {            try {                Thread.sleep(2 * 1000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(Thread.currentThread().getName() + "   " + index);        });    }    executor.shutdown();}

执行结果

四、线程池的作用

线程池的作用主要是为了提升系统的性能以及使用率。文章刚开始就提到,如果我们使用最简单的方式创建线程,如果用户量比较大,那么就会产生很多创建和销毁线程的动作,这会导致服务器在创建和销毁线程上消耗的性能可能要比处理实际业务花费的时间和性能更多。线程池就是为了解决这种这种问题而出现的。

同样思想的设计还有很多,比如数据库连接池,由于频繁的连接数据库,然而创建连接是一个很消耗性能的事情,所有数据库连接池就出现了。

java assert使用场景_Java线程池的四种用法与使用场景相关推荐

  1. newsinglethreadexecutor使用场景_Java线程池的四种用法与使用场景

    来源公众号一个程序员的成长 ,作者小涛 一.如下方式存在的问题 new Thread() { @Override public void run() { // 业务逻辑 }}.start(); 1.首 ...

  2. 第二十八期:Java线程池的四种用法与使用场景

    线程池的作用主要是为了提升系统的性能以及使用率.文章刚开始就提到,如果我们使用最简单的方式创建线程,如果用户量比较大,那么就会产生很多创建和销毁线程的动作,这会导致服务器在创建和销毁线程上消耗的性能可 ...

  3. 线程池 java 新建方式_Java线程池的四种创建方式

    Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程. newFi ...

  4. java多线程——Executors线程池的四种用法简单解析

    1.Executors.newFixedThreadPool(5)    是创建一个线程池,池子里面有5个线程,任务数多余5个时,超出的任务队列中排队等候执行 2.Executors.newCache ...

  5. Java线程池的四种创建方式

    Java线程池的四种创建方式 Java使用Thread类来表示线程,所有的线程都是Thread类或者是他的子类.Java有四种方式来创建线程. (1)继承Thread类创建线程 (2)实现Runnab ...

  6. java io密集型任务_Java线程池讲解——针对IO密集型任务

    sap java开发技术详解&mdash基础 94.01元 (需用券) 去购买 > 针对 IO 密集型的任务,我们可以针对原本的线程池做一些改造,从而可以提高任务的处理效率. 基本 在阿 ...

  7. java线程池分类_JAVA线程池有几种类型?

    常用的JAVA线程池有以下几种类型: 1.newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程. 这种类型的线程池特点是 ...

  8. java new thread参数_java线程池01-ThreadPoolExecutor构造方法参数的使用规则

    为了更好的使用多线程,JDK提供了线程池供开发人员使用,目的在于减少线程的创建和销毁次数,以此达到线程的重复利用. 其中ThreadPoolExecutor是线程池中最核心的一个类,我们先简单看一下这 ...

  9. java多线程 占用内存_java线程池常驻线程占内存吗

    看了下代码: public void run() { try { Runnable task = firstTask; firstTask = null; while (task != null || ...

最新文章

  1. RxSwift 小记 Error Handling Operators(catchError,retry)
  2. 解决Windows对JDK默认版本切换问题
  3. find命令应用详解
  4. java 提供的排序方法_请给出java几种排序方法
  5. 自主云服务器处理器_云服务器哪家的CPU最便宜且好用
  6. spring boot 所有引用jar包及作用
  7. Docker最全教程——数据库容器化之持久保存数据(十一)
  8. message show_once这个标志位的用法
  9. 特斯拉是l3还是l2_比特斯拉还“高一级”,长安的“L3级自动驾驶”到底什么来头?...
  10. Web前端笔记-two.js实现坐标定位(动画效果非瞬移定位)
  11. 一起来玩树莓派--解决This must be accepted explicitly before updates for this repository can be applied问题
  12. 数据库连接池php-cp介绍
  13. [转载] 如何使用Python 实现秒表功能?
  14. 老段51CTO会员卡 限时半价
  15. Pandas循环提速 7 万多倍是怎么实现的?
  16. 一个程序员父亲的呼吁:不要教你的孩子从小学编程!
  17. java需要知道哪些英语单词_70个学习JAVA必背的英语单词,了解下
  18. MapABC 地图定位
  19. Ubuntu无法切换中文输入法的解决方法
  20. UI面试常见问题及回答

热门文章

  1. 透过三翼鸟,看品牌背后的“有效创新”
  2. linux默认开启sudo_Sudo漏洞允许非特权Linux和macOS用户以root身份运行命令
  3. python统计字符在文件中出现的次数_python字符串中字符出现次数(python获取字符串个数)...
  4. linux 进程 setuid,Linux SetUID(SUID)文件特殊权限用法详解
  5. 关于解决安装pwndbg问题sys.stderr.write(f“ERROR: {exc}“) /usr/bin/python3.5: No module named ensurepip
  6. Python中defaultdict函数的使用方法
  7. Python手动实现kmeans聚类和调用sklearn实现
  8. 67道 Python自动化面试题
  9. Python的filter方法实现筛选功能
  10. signal c语言,C 库函数