java并发编程(3)线程池
2017-09-13 本文已影响25人
monkey01
该篇是本系列的第三篇,本篇主要介绍日常开发过程中常用的线程池,在jdk中已经给我们提供了很多线程池创建方法,可以方便的快速创建线程,最常用的创建线程池的方法是调用Executors的new系列方法newFixedThreadPool()、newCachedThreadPool()、newSingleThreadExecutor()等,这些方法看名字就很好理解具体含义,newFixedThreadPool表示创建一个固定线程的线程池,newCachedThreadPool表示根据实际创建的线程数进行动态创建线程池,newSingleThreadExecutor为创建一个只有一个线程的线程池,这些所有的创建线程池的方法都可以将ThreadFactory作为创建线程池构造函数的入参,在很多场合我们需要自定义线程工厂来满足我们的需求。
创建固定线程池实例,入参为线程池数量:
ExecutorService es = Executors.newFixedThreadPool(5);
自定义线程池:
ExecutorService es2 = new ThreadPoolExecutor(5, 10, 1000, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>(), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
System.out.println("create " + t);
return t;
}
}, new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println(r.toString() + " is discard!");
}
});
ThreadPoolExecutor的构造函数如下,:
ThreadPoolExecutor(int corePoolSize,//核心线程数,启动时候会启动这个数量的线程,也不会删除线程
int maximumPoolSize,//最大线程池数量
long keepAliveTime,//线程保持时间
TimeUnit unit,//保持时间单位
BlockingQueue<Runnable> workQueue,//等待队列,默认使用SynchronousQueue就可以
ThreadFactory threadFactory,//可以自定义ThreadFactory进行特殊处理
RejectedExecutionHandler handler)//超出线程后的拒绝策略,可以自定义拒绝的处理方式,用的比较多的策略就是放弃
通过下面的例子分别创建了两个线程池,实例es是创建的固定线程数的线程池,循环10次提交线程,因为线程池数量为5,我们发现打出的线程分两批显示,5个5个显示出来,并且线程id是复用的,如下显示:
1505295665359:thread id = 9
1505295665359:thread id = 10
1505295665359:thread id = 11
1505295665359:thread id = 12
1505295665359:thread id = 13
1505295666361:thread id = 11
1505295666361:thread id = 12
1505295666362:thread id = 13
1505295666362:thread id = 10
1505295666362:thread id = 9
实例es2是自定义线程池,自定义的丢弃策略为打印丢弃线程直接丢弃不处理,线程池大小为10,线程循环执行20次,有10次线程处理被丢弃,执行结果如下:
create Thread[Thread-0,5,main]
create Thread[Thread-1,5,main]
1505295922428:thread id = 9
create Thread[Thread-2,5,main]
1505295922428:thread id = 10
create Thread[Thread-3,5,main]
1505295922428:thread id = 11
create Thread[Thread-4,5,main]
1505295922429:thread id = 12
create Thread[Thread-5,5,main]
1505295922429:thread id = 13
create Thread[Thread-6,5,main]
1505295922429:thread id = 14
create Thread[Thread-7,5,main]
1505295922429:thread id = 15
create Thread[Thread-8,5,main]
1505295922430:thread id = 16
create Thread[Thread-9,5,main]
1505295922430:thread id = 17
1505295922430:thread id = 18
java.util.concurrent.FutureTask@6f94fa3e is discard!
java.util.concurrent.FutureTask@5e481248 is discard!
java.util.concurrent.FutureTask@66d3c617 is discard!
java.util.concurrent.FutureTask@63947c6b is discard!
java.util.concurrent.FutureTask@2b193f2d is discard!
java.util.concurrent.FutureTask@355da254 is discard!
java.util.concurrent.FutureTask@4dc63996 is discard!
java.util.concurrent.FutureTask@d716361 is discard!
java.util.concurrent.FutureTask@6ff3c5b5 is discard!
java.util.concurrent.FutureTask@3764951d is discard!
上面例子的全部代码如下:
public class ThreadPoolBasic {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
MyThread myThread2 = new MyThread();
ExecutorService es = Executors.newFixedThreadPool(5);
for(int i=0; i<10; i++){
es.submit(myThread);
}
ExecutorService es2 = new ThreadPoolExecutor(5, 10, 1000, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>(), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
System.out.println("create " + t);
return t;
}
}, new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println(r.toString() + " is discard!");
}
});
System.out.println("====custom threadfactoty====");
for(int i=0; i<20; i++){
es2.submit(myThread2);
}
es.shutdown();
es2.shutdown();
}
public static class MyThread implements Runnable{
@Override
public void run() {
System.out.println(System.currentTimeMillis() + ":thread id = " + Thread.currentThread().getId());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
通过这个例子是不是发现jdk的线程池使用很简单,自己动手写个demo尝试下吧。