1)BlockingQueue队列实现线程池
应用场景1:系统需要开启多线程接收日志文件,有时开启线程数过大占用内存,因此启用线程池处理接收日志。
例如:创建一个线程池如下
要求:1.线程池基本大小corePoolSize为10
2.线程池最大maximumPoolSize为15
3.线程活动保持时间keepAliveTime为100
4.线程活动保持时间单位TimeUnit为毫秒MILLISECONDS
/**
* @ 接收日志文件,启用线程池
* @author lim
* @date 2017-04-01
*/
public class ReapFileThreadPool {
private static ThreadPoolExecutor executor =
new ThreadPoolExecutor(10, 15, 100, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
public static void execute(Runnable myThread){
executor.execute(myThread);
}
}
线程池工作原理
1.如果运行的线程数量少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队。(什么意思?如果当前运行的线程小于corePoolSize,则任务根本不会存放,添加到queue中
2.如果运行的线程等于或多于 corePoolSize,则 Executor 始终首选将请求加入队列,而不添加新的线程。
3.如果无法将请求加入队列(队列已满),则创建新的线程,除非创建此线程超出 maximumPoolSize,如果超过,在这种情况下,新的任务将被拒绝。
2)BlockingQueue实现消息队列
应用场景2:应用BlockingQueue队列实现后台数据处理进程展示,前台定时读取队列信息。
public class BlockingQueueLog {
final static int FILE_QUEUE_SIZE = 50;// 阻塞队列大小
final static BlockingQueue<String> queue = new ArrayBlockingQueue<String>(
FILE_QUEUE_SIZE);
public static boolean offString(String msg){
return queue.offer(msg);
}
public static List<Object> pollString(){
List<Object> rlist = new ArrayList<Object>();
while(true){
Object msg = queue.poll();
if(msg == null) break;
rlist.add(msg);
}
return rlist;
}
public static void clearString(){
queue.clear();
}
}
注:ArrayBlockingQueue和LinkedBlockingQueue区别
ArrayBlockingQueue实现的队列,生产者和消费锁没有分离。(适合应用场景2
LinkedBlockingQueue实现的队列,生产者和消费者的锁是分离的,所以能提高队列的并发性能。(适合应用场景1
如何设置线程池的大小以及队列的大小,参考了以下大神讲解
合理的设置线程池队列长度