zoukankan      html  css  js  c++  java
  • 通过Executor来启动线程比用Thread的start()更好

    java5为什么引入Executor线程池框架

    1.new Thread()的缺点

    (1) 每次new Thread()耗费性能 
    (2) 调用new Thread()创建的线程缺乏管理,被称为野线程,而且可以无限制创建,之间相互竞争,会导致过多占用系统资源,使系统瘫痪
    (3) 不利于扩展,比如定时执行、定期执行

    2.采用线程池的优点

    (1) 重用存在的线程,减少对象创建、销毁的开销,性能佳 
    (2) 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞 
    (3) 提供定时执行、定期执行、单线程、并发数控制等功能

    java通过Executor提供4种线程池

    1.newCachedThreadPool 创建一个可缓存的线程池,调用execute将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程

    示例:

    ExecutorService executor = Executors.newCachedThreadPool();
    for (int i = 0; i < 10; i++) {
         Runnable task = new Runnable() {
             @Override
             public void run() {
                 System.out.println(Thread.currentThread().getName());
             }
         };
         executor.execute(task);
    }

    运行结果:可以看出缓存线程池大小是不定值,可以需要创建不同数量的线程,在使用缓存型池时,先查看池中有没有以前创建的线程,如果有,就复用.如果没有,就新建新的线程加入池中,缓存型池子通常用于执行一些生存期很短的异步型任务。

    2.newFixedThreadPool 创建固定数目线程的线程池,可控制线程最大并发数,超出的线程会在队列中等待

    示例:

    ExecutorService executor = Executors.newFixedThreadPool(2);
    for (int i = 0; i < 10; i++) {
         Runnable task = new Runnable() {
             @Override
             public void run() {
            System.out.println(Thread.currentThread().getName()); } }; executor.execute(task); }

    运行结果:总共只会创建2个线程, 开始执行2个线程,当2个线程都处于活动状态,再次提交的任务都会加入队列等到其他线程运行结束,当线程处于空闲状态时会被下一个任务复用。

    3.newScheduledThreadPool 创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类

    示例:

    ExecutorService executor = Executors.newScheduledThreadPool(2);
    for (int i = 0; i < 10; i++) {
         Runnable task = new Runnable() {
             @Override
             public void run() {
            System.out.println(Thread.currentThread().getName()); } }; executor.schedule(task, 3, TimeUnit.SECONDS); }

    运行结果:和newFixedThreadPool类似,不同的是newScheduledThreadPool是延时指定时间之后才执行。

    4.newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行

    示例:

    ExecutorService executor = Executors.newScheduledThreadPool();
    for (int i = 0; i < 10; i++) {
         Runnable task = new Runnable() {
             @Override
             public void run() {
                 System.out.println(Thread.currentThread().getName());
             }
         };
         executor.execute(task);
    }

    运行结果:只会创建一个线程,当上一个执行完之后才会执行第二个。

     

    ExecutorService中submit和execute的区别:

    相同点:submit和execute都是 ExecutorService 的方法,都是添加线程到线程池中

    不同点:submit 有返回值 返回Future , execute没有,Future可以执行cancle方法(取消执行 ),可以通过get()方法,判断是否执行成功(null表示执行成功)

     

  • 相关阅读:
    自编码器AutoEncoder,降噪自编码器DAE,稀疏自编码器SAE,变分自编码器VAE 简介
    经验模式分解EMD与集合经验模态分解EEMD
    Adversarial Faces
    网络权重初始化方法 常数初始化、Lecun、Xavier与He Kaiming
    信息熵、交叉熵、KL散度、JS散度、Wasserstein距离
    神经网络前向传播和反向传播公式 详细推导
    Softmax 原理及 Sigmoid和Softmax用于分类的区别
    However, but, yet, while, whereas 表转折的区别; while, whereas区别
    阿里云mysql数据库恢复到本地
    js 14位字符串 转日期
  • 原文地址:https://www.cnblogs.com/super-yu/p/7190280.html
Copyright © 2011-2022 走看看