四种构建线程池的区别及特点?

1. newCachedThreadPool

  • 特点:newCachedThreadPool创建一个可缓存线程池,如果当前线程池的长度超过了处理的需要时,它可以灵活的回收空闲的线程,当需要增加时, 它可以灵活的添加新的线程,而不会对池的长度作任何限制

  • 缺点:他虽然可以无线的新建线程,但是容易造成堆外内存溢出,因为它的最大值是在初始化的时候设置为 Integer.MAX_VALUE,一般来说机器都没那么大内存给它不断使用。当然知道可能出问题的点,就可以去重写一个方法限制一下这个最大值

  • 总结:线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。

  • 代码示例:

    package com.lijie;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class TestNewCachedThreadPool {
        public static void main(String[] args) {
            // 创建无限大小线程池,由jvm自动回收
            ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
            for (int i = 0; i < 10; i++) {
                final int temp = i;
                newCachedThreadPool.execute(new Runnable() {
                    public void run() {
                        try {
                            Thread.sleep(100);
                        } catch (Exception e) {
                        }
                        System.out.println(Thread.currentThread().getName() + ",i==" + temp);
                    }
                });
            }
        }
    }
    

2.newFixedThreadPool

  • 特点:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。定长线程池的大小最好根据系统资源进行设置。

  • 缺点:线程数量是固定的,但是阻塞队列是无界队列。如果有很多请求积压,阻塞队列越来越长,容易导致OOM(超出内存空间)

  • 总结:请求的挤压一定要和分配的线程池大小匹配,定线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()

Runtime.getRuntime().availableProcessors()方法是查看电脑CPU核心数量)

  • 代码示例:

    package com.lijie;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class TestNewFixedThreadPool {
        public static void main(String[] args) {
            ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3);
            for (int i = 0; i < 10; i++) {
                final int temp = i;
                newFixedThreadPool.execute(new Runnable() {
                    public void run() {
                        System.out.println(Thread.currentThread().getName() + ",i==" + temp);
                    }
                });
            }
        }
    }
    

3.newScheduledThreadPool

  • 特点:创建一个固定长度的线程池,而且支持定时的以及周期性的任务执行,类似于Timer(Timer是Java的一个定时器类)

  • 缺点:由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务(比如:一个任务出错,以后的任务都无法继续)。

  • 代码示例:

    package com.lijie;
    
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class TestNewScheduledThreadPool {
        public static void main(String[] args) {
            //定义线程池大小为3
            ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(3);
            for (int i = 0; i < 10; i++) {
                final int temp = i;
                newScheduledThreadPool.schedule(new Runnable() {
                    public void run() {
                        System.out.println("i:" + temp);
                    }
                }, 3, TimeUnit.SECONDS);//这里表示延迟3秒执行。
            }
        }
    }
    

4.newSingleThreadExecutor

  • 特点:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它,他必须保证前一项任务执行完毕才能执行后一项。保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

  • 缺点:缺点的话,很明显,他是单线程的,高并发业务下有点无力

  • 总结:保证所有任务按照指定顺序执行的,如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它

  • 代码示例:

    package com.lijie;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class TestNewSingleThreadExecutor {
        public static void main(String[] args) {
            ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
            for (int i = 0; i < 10; i++) {
                final int index = i;
                newSingleThreadExecutor.execute(new Runnable() {
                    public void run() {
                        System.out.println(Thread.currentThread().getName() + " index:" + index);
                        try {
                            Thread.sleep(200);
                        } catch (Exception e) {
                        }
                    }
                });
            }
        }
    }
    

线程池都有哪些状态?

  • RUNNING:这是最正常的状态,接受新的任务,处理等待队列中的任务。
  • SHUTDOWN:不接受新的任务提交,但是会继续处理等待队列中的任务。
  • STOP:不接受新的任务提交,不再处理等待队列中的任务,中断正在执行任务的线程。
  • TIDYING:所有的任务都销毁了,workCount 为 0,线程池的状态在转换为 TIDYING 状态时,会执行钩子方法 terminated()。
  • TERMINATED:terminated()方法结束后,线程池的状态就会变成这个。

线程池中 submit() 和 execute() 方法有什么区别?

  • 相同点:
    • 相同点就是都可以开启线程执行池中的任务。
  • 不同点:
    • 接收参数:execute()只能执行 Runnable 类型的任务。submit()可以执行 Runnable 和 Callable 类型的任务。
    • 返回值:submit()方法可以返回持有计算结果的 Future 对象,而execute()没有
    • 异常处理:submit()方便Exception处理


作者:小杰要吃蛋
链接:https://juejin.cn/post/6844904125755293710
来源:掘金

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java平台是一种广泛应用于软件开发领域的计算机编程语言和平台。它的平台特点主要有跨平台性、安全性和可移植性。Java平台可以运用各种设计模式,下面列举了5种常见的设计模式。 1. 单例模式:单例模式确保一个类只能创建一个实例,通过使用私有的构造函数和静态方法来实现。在Java平台中,常常用于创建数据库连接池、线程池等只需要一个实例的场景。 2. 工厂模式:工厂模式是一种创建型设计模式,用于创建对象的方法抽象,通过将对象的创建和使用解耦,对客户端隐藏对象的创建细节。Java平台中常用的工厂模式有简单工厂模式、工厂方法模式和抽象工厂模式。 3. 观察者模式:观察者模式是一种行为型设计模式,通过定义了对象之间的一对多关系,使得当一个对象发生改变时,所有依赖于它的对象都会收到通知并自动更新。在Java平台中,常见的观察者模式应用包括事件监听、消息队列等。 4. 适配器模式:适配器模式是一种结构型设计模式,用于解决两个接口不兼容的问题。适配器模式通过将一个类的接口转换成客户端期望的另一个接口,使得原本由于接口不匹配而无法工作的类可以一起工作。在Java平台中,常见的适配器模式应用包括各种适配器类、Wrapper类等。 5. 策略模式:策略模式是一种行为型设计模式,通过定义一系列可以相互替换的算法族,使得每个算法都可以独立地变化和封装。在Java平台中,策略模式常被用于实现排序算法、搜索算法等。 ### 回答2: Java平台是一种广泛使用的软件开发平台,其特点是跨平台性和可移植性,可以在各种设备和操作系统上运行。Java平台提供了一种丰富的类库和工具,开发人员可以使用这些工具和类库来创建各种类型的应用程序,包括Web应用程序、移动应用程序和企业级应用程序等。 设计模式是一种在软件开发过程中广泛应用的重要思想,它提供了解决常见问题的模板和方法。Java平台提供了很多设计模式的实现,开发人员可以根据自己的需求选择适合的设计模式来解决问题。 以下是5种常见的设计模式,并介绍如何在Java平台上运用它们: 1. 单例模式:保证一个类只有一个实例,并提供一个全局访问点。在Java平台上可以使用私有构造函数和静态变量来实现单例模式。 2. 工厂模式:将对象的创建与使用分离,通过工厂类来创建对象。在Java平台上可以使用工厂方法或抽象工厂来实现工厂模式。 3. 装饰模式:动态地给一个对象添加额外的功能,同时又不改变其接口。在Java平台上可以使用装饰器模式来实现装饰模式。 4. 观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。在Java平台上可以使用观察者模式来实现事件监听和处理。 5. 适配器模式:将一个类的接口转换成客户希望的另外一个接口。在Java平台上可以使用适配器模式来实现接口的兼容和转换。 以上是在Java平台上运用5种设计模式的简要介绍。设计模式可以提高代码的可复用性和灵活性,帮助开发人员更好地解决问题。 ### 回答3: Java平台是一种广泛使用的编程语言和计算平台,它为开发者提供了丰富的功能和工具来构建各种应用程序。在Java平台的开发过程中,开发者可以运用不同的设计模式来提高代码的可重用性、可维护性和可扩展性。下面介绍五种常见的设计模式。 1. 单例模式(Singleton Pattern):单例模式用于确保一个类只有一个实例,并且提供了全局访问点。这对于需要统一访问和管理资源的场景非常有用,例如数据库连接或配置文件读取等。 2. 工厂模式(Factory Pattern):工厂模式用于创建对象,隐藏对象的创建细节并提供一个公共接口。通过工厂模式,可以使客户端只依赖于工厂接口而不需要关注具体的实现类。这种模式有助于降低耦合度并提高代码的可扩展性。 3. 观察者模式(Observer Pattern):观察者模式定义了一种一对多的依赖关系,当一个对象状态发生变化时,其所有依赖者都会收到通知并进行相应的更新。这种模式常用于事件驱动的系统,如图形界面中的事件监听器。 4. 策略模式(Strategy Pattern):策略模式定义了一组算法,并将每个算法封装在独立的类中,使它们可以相互替代。通过使用策略模式,可以在运行时动态地选择不同的算法来完成相同的任务,提高了代码的灵活性和可扩展性。 5. 装饰者模式(Decorator Pattern):装饰者模式用于在不改变原有对象的结构的情况下,给对象增加新的行为或功能。通过将对象包装在一个装饰者类中,可以在运行时动态地添加功能,而不需要修改原有代码。这种模式有助于遵循开闭原则,即对扩展是开放的,对修改是关闭的。 以上五种设计模式在Java平台中被广泛应用,它们可以帮助开发者编写更加高效、可维护和易于扩展的代码。熟练掌握这些设计模式对于Java开发者来说是非常重要的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值