1.示例
/** * 线程运行demo,运行时打出线程id以及传入线程中参数 */ public class ThreadRunner implements Runnable { private final SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss.SSS"); /** * 线程私有属性,创建线程时创建 */ private Integer num; public ThreadRunner(Integer num) { this.num = num; } @Override public void run() { System.out.println("thread:" + Thread.currentThread().getName() + ",time:" + format.format(new Date()) + ",num:" + num); try {//使线程睡眠,模拟线程阻塞情况 TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }
2.FixedThreadPool -- 有一个固定大小的线程池
public static void main(String[] args) { ExecutorService pool = Executors.newFixedThreadPool(4); for(int i = 0 ; i < 50 ; i++){ pool.submit(new ThreadRunner((i + 1))); } pool.shutdown(); }
该方式中:
--池中线程数量固定,不会发生变化
--使用无界的LinkedBlockingQueue,要综合考虑生成与消费能力,生成过剩可能导致堆内存溢出.
--使用一些很稳定很固定的正规并发线程,多用于服务器.
3.CachedThreadPool -- 随机生成线程数量
public static void main(String[] args) { ExecutorService pool = Executors.newCachedThreadPool(); for(int i = 0 ; i < 50 ; i++){ pool.submit(new ThreadRunner((i + 1))); } pool.shutdown(); }
该方式中:
--池中线程数量随着处理数据增加而怎加
--线程数并不是一直增加,如果有新任务需要执行时,首先查询池中是否有空闲的线程并且还为到空闲截止时间,如果有,则使用空闲线程没如果没有,则创建新线程放入池中.
--用于执行一些生存期很短的异步任务,不适用IO等长延时操作,因为这可能会创建大量线程,导致系统崩溃.
--使用SynchronousQueue作为阻塞队列,如果有新任务进入队列,必须队列中数据被其他线程处理,否则回等待.
4.Single ThreadExecutor -- 简单顺序执行
public static void main(String[] args) { ExecutorService pool = Executors.newSingleThreadExecutor(); for(int i = 0 ; i < 50 ; i++){ pool.submit(new ThreadRunner((i + 1))); } pool.shutdown(); }
--线程中只有一个线程在执行
--适用于有明确执行顺序但是不影响主线程的任务,压入池中的任务会按照队列顺序执行
--适用无界的LinkedBlockingQueue,要综合考虑生成与消费能力,生成过剩,可能导致堆内存溢出.
5.关键词说明
--corePoolSize:线程池核心线程数量
--1.如果池中线程数量少于核心线程池数量,则直接新建线程处理当前任务
--2.核心线程池空闲不会被回收.
--3.当池中无空闲线程时,新任务将被添加到阻塞队列
--maximumPoolSize: 线程池最大线程数量
--1.当阻塞队列已满,并且有新任务还在入队是,创建新的线程处理,直到线程数大于maximumPoolSize
--2.超出corePoolSize部分的线程超过空闲时间会被回收
--3.当线程已经超过corePoolSize,并且队列容量已满,则拒绝入队
--keepAliveTime unit: 线程存活时间
--1.当线程超出corePoolSize时生效
--2.线程空余keepAliveTime后,将被回收
--workQueue: 线程使用阻塞队列
--ThreadFactory:创建线程池工厂
-用于控制创建线程或者销毁线程时加入其它逻辑
import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpHandler;
public class MyHttpServer{
//初始化server服务器端
private static HttpServer httpServer = null;
//初始化executor线程池
private static ExecutorService executor = null;
public static void start(int port, HttpHandler handler,List<String> paths) throws Exception{
//创建一个随机大小的线程池
executor = Executors.newCachedThreadPool();
//实现HTTP server 其中port为端口号
httpServer = HttpServer.create(new InetSocketAddress(port), 0);
//设置server端的线程池
httpServer.setExecutor(executor);
if(paths!=null&&paths.size()>0){
for(int i=0;i<paths.size();i++){
//使用handler来处理/的请求
httpServer.createContext(paths.get(i), handler);
}
}else{
httpServer.createContext("/", handler);
}
//启动服务
httpServer.start();
}
public static void stop() {
executor.shutdown();
httpServer.stop(0);
}
}