java ExecutorService与Executors学习总结

由于所做的一个功能模块需要以非常高的频率处理数据, 所以决定采用线程池来做. 

刚好前一段时间使用netty做了一个长连接服务器,  当中有这样一段话, 

// 建立通道工厂
        ChannelFactory factory = new NioServerSocketChannelFactory(
                Executors.newCachedThreadPool(),
                Executors.newCachedThreadPool());

        ServerBootstrap bootstrap = new ServerBootstrap(factory);

绿色部分, 引出以下几个要学习了解的知识点:

1. Executors是什么?

2. Executors.newCachedThreadPool() 返回的ExecutorService 是什么

3. 二者如何组合使用

---------------------------------------------------------------------------------------------------------------------

1. 类 Executors

此类中提供的一些方法有:

1.1 public static ExecutorService newCachedThreadPool()
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。
 
1.2 public static ExecutorService newFixedThreadPool(int nThreads)
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
 
1.3 public static ExecutorService newSingleThreadExecutor()
创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。

这三个方法都可以配合接口 ThreadFactory 的实例一起使用。并且返回一个 ExecutorService 接口的实例。

2. 接口 ThreadFactory

根据需要创建新线程的对象。使用线程工厂就无需再手工编写对 new Thread 的调用了,从而允许应用程序使用特殊的线程子类、属性等等。
此接口最简单的实现就是:
class SimpleThreadFactory implements ThreadFactory {
   public Thread newThread(Runnable r) {
     return new Thread(r);
   }
 }

3. 接口ExecutorService
该接口提供了管理终止的方法。

4.创建标准线程池启动线程
4.1 提供一个简单的实现Runnable接口的线程

MyThread.java
package com.zj.concurrency.executors;
 
public class MyThread implements Runnable {
    private int count = 1, number;
 
    public MyThread(int num) {
       number = num;
       System.out.println("Create Thread-" + number);
    }
 
    public void run() {
       while (true) {
           System.out.println("Thread-" + number + " run " + count+" time(s)");
           if (++count == 3)
              return;
       }
    }
}

这个线程会打印出相应的创建和执行信息。
 
4.2使用CachedThreadPool启动线程

CachedThreadPool.java

package com.zj.concurrency.executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class CachedThreadPool {
    public static void main(String[] args) {
       ExecutorService exec = Executors.newCachedThreadPool();
       for (int i = 0; i < 5; i++)
           exec.execute(new MyThread(i));
       exec.shutdown();
    }
}

结果:
Create Thread-0
Create Thread-1
Create Thread-2
Create Thread-3
Thread-0 run 1 time(s)
Thread-0 run 2 time(s)
Thread-1 run 1 time(s)
Thread-1 run 2 time(s)
Thread-2 run 1 time(s)
Thread-2 run 2 time(s)
Create Thread-4
Thread-4 run 1 time(s)
Thread-4 run 2 time(s)
Thread-3 run 1 time(s)
Thread-3 run 2 time(s)

4.3 使用FixedThreadPool启动线程

FixedThreadPool.java
package com.zj.concurrency.executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class FixedThreadPool {
    public static void main(String[] args) {
       ExecutorService exec = Executors.newFixedThreadPool(2);
       for (int i = 0; i < 5; i++)
           exec.execute(new MyThread(i));
       exec.shutdown();
    }
}

结果:
Create Thread-0
Create Thread-1
Create Thread-2
Create Thread-3
Create Thread-4
Thread-0 run 1 time(s)
Thread-0 run 2 time(s)
Thread-2 run 1 time(s)
Thread-2 run 2 time(s)
Thread-3 run 1 time(s)
Thread-3 run 2 time(s)
Thread-4 run 1 time(s)
Thread-4 run 2 time(s)
Thread-1 run 1 time(s)
Thread-1 run 2 time(s)
 
4.4 使用SingleThreadExecutor启动线程

SingleThreadExecutor.java
package com.zj.concurrency.executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class SingleThreadExecutor {
    public static void main(String[] args) {
       ExecutorService exec = Executors.newSingleThreadExecutor();
       for (int i = 0; i < 5; i++)
           exec.execute(new MyThread(i));
       exec.shutdown();
    }
}

结果:
Create Thread-0
Create Thread-1
Create Thread-2
Create Thread-3
Create Thread-4
Thread-0 run 1 time(s)
Thread-0 run 2 time(s)
Thread-1 run 1 time(s)
Thread-1 run 2 time(s)
Thread-2 run 1 time(s)
Thread-2 run 2 time(s)
Thread-3 run 1 time(s)
Thread-3 run 2 time(s)
Thread-4 run 1 time(s)
Thread-4 run 2 time(s)

5.配合ThreadFactory接口的使用
我们试图给线程加入daemon和priority的属性设置。

5.1设置后台线程属性

DaemonThreadFactory.java
package com.zj.concurrency.executors.factory;
import java.util.concurrent.ThreadFactory;
 
public class DaemonThreadFactory implements ThreadFactory {
    public Thread newThread(Runnable r) {
       Thread t = new Thread(r);
       t.setDaemon(true);
       return t;
    }
}

5.2 设置优先级属性
最高优先级

MaxPriorityThreadFactory.java
package com.zj.concurrency.executors.factory;
import java.util.concurrent.ThreadFactory;
 
public class MaxPriorityThreadFactory implements ThreadFactory {
    public Thread newThread(Runnable r) {
       Thread t = new Thread(r);
       t.setPriority(Thread.MAX_PRIORITY);
       return t;
    }
}

最低优先级MinPriorityThreadFactory.java
package com.zj.concurrency.executors.factory;
import java.util.concurrent.ThreadFactory;
 
public class MinPriorityThreadFactory implements ThreadFactory {
    public Thread newThread(Runnable r) {
       Thread t = new Thread(r);
       t.setPriority(Thread.MIN_PRIORITY);
       return t;
    }
}

5.3启动带有属性设置的线程

ExecFromFactory.java
package com.zj.concurrency.executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.zj.concurrency.executors.factory.DaemonThreadFactory;
import com.zj.concurrency.executors.factory.MaxPriorityThreadFactory;
import com.zj.concurrency.executors.factory.MinPriorityThreadFactory;
 
public class ExecFromFactory {
    public static void main(String[] args) throws Exception {
       ExecutorService defaultExec = Executors.newCachedThreadPool();
       ExecutorService daemonExec = Executors
              .newCachedThreadPool(new DaemonThreadFactory());
       ExecutorService maxPriorityExec = Executors
              .newCachedThreadPool(new MaxPriorityThreadFactory());
       ExecutorService minPriorityExec = Executors
              .newCachedThreadPool(new MinPriorityThreadFactory());
       for (int i = 0; i < 10; i++)
           daemonExec.execute(new MyThread(i));
       for (int i = 10; i < 20; i++)
           if (i == 10)
              maxPriorityExec.execute(new MyThread(i));
           else if (i == 11)
              minPriorityExec.execute(new MyThread(i));
           else
              defaultExec.execute(new MyThread(i));
    }
}

结果:
Create Thread-0
Create Thread-1
Create Thread-2
Create Thread-3
Thread-0 run 1 time(s)
Thread-0 run 2 time(s)
Thread-1 run 1 time(s)
Thread-1 run 2 time(s)
Thread-2 run 1 time(s)
Thread-2 run 2 time(s)
Create Thread-4
Thread-4 run 1 time(s)
Thread-4 run 2 time(s)
Create Thread-5
Thread-5 run 1 time(s)
Thread-5 run 2 time(s)
Create Thread-6
Create Thread-7
Thread-7 run 1 time(s)
Thread-7 run 2 time(s)
Create Thread-8
Thread-8 run 1 time(s)
Thread-8 run 2 time(s)
Create Thread-9
Create Thread-10
Thread-10 run 1 time(s)
Thread-10 run 2 time(s)
Create Thread-11
Thread-9 run 1 time(s)
Thread-9 run 2 time(s)
Thread-6 run 1 time(s)
Thread-6 run 2 time(s)
Thread-3 run 1 time(s)
Thread-3 run 2 time(s)
Create Thread-12
Create Thread-13
Create Thread-14
Thread-12 run 1 time(s)
Thread-12 run 2 time(s)
Thread-13 run 1 time(s)
Thread-13 run 2 time(s)
Create Thread-15
Thread-15 run 1 time(s)
Thread-15 run 2 time(s)
Create Thread-16
Thread-16 run 1 time(s)
Thread-16 run 2 time(s)
Create Thread-17
Create Thread-18
Create Thread-19
Thread-14 run 1 time(s)
Thread-14 run 2 time(s)
Thread-17 run 1 time(s)
Thread-17 run 2 time(s)
Thread-18 run 1 time(s)
Thread-18 run 2 time(s)
Thread-19 run 1 time(s)
Thread-19 run 2 time(s)
Thread-11 run 1 time(s)
Thread-11 run 2 time(s)



更多推荐文章:

http://www.cnblogs.com/yezhenhan/archive/2012/01/07/2315645.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
`ExecutorService executorService = Executors.newFixedThreadPool(20);` 这行代码是 Java 中创建一个固定线程池的方式。 **解释如下:** 1. **`Executors` 类**: 这是一个工具类,在 Java 中用于方便地创建 `ExecutorService` 的实例。它提供了一些静态方法来创建不同类型的服务,如固定大小的线程池、无限制的线程池等。 2. **`newFixedThreadPool(int nThreads)`**: 这是 `Executors` 类的一个静态工厂方法,专门用于创建一个固定大小的线程池。其中 `nThreads` 参数表示创建线程池所需的线程数量。在这个例子中,我们创建了一个可以同时运行最多 20 个线程的线程池。 3. **创建线程池的好处**: - **提高效率**: 线程池预先创建了指定数量的线程,避免了每次需要新线程时频繁创建和销毁线程带来的开销。 - **控制并发度**: 可以通过设置线程池的最大线程数来控制系统的最大并发量。 - **更好的资源管理**: 避免过多线程导致的操作系统级别的调度开销,有助于性能优化。 - **状态管理**: 当某个线程完成任务并返回线程池时,它可以立即用于新的任务,无需等待新线程的启动过程。 4. **如何使用 ExecutorService**: 您可以向 `executorService` 提交任务,通常会使用 `submit(Runnable task)` 方法来提交一个任务到线程池中。每个任务都会由线程池内部的任意空闲线程处理。当所有可用线程都被占用时,后续的任务将暂时排队等待执行。 5. **结束线程池**: 当您不再需要这个线程池时,可以通过调用 `shutdown()` 或者 `shutdownNow()` 方法来停止接受新任务,并等待当前正在运行的所有任务完成后关闭线程池。 6. **错误处理**: 如果尝试创建一个无法容纳更多线程的固定大小线程池时,可能会抛出 `IllegalArgumentException` 异常,因为提供的参数 `nThreads` 超过了系统能够支持的最大线程数量。 记住合理选择线程池大小对于应用的性能至关重要,过大可能导致资源浪费,过小则可能无法满足高并发场景下的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值