多线程池newFixedThreadPool之动态多线程池去做线程池隔离


声明:本文转载自https://my.oschina.net/u/2241980/blog/1555637,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

背景

     本文不是讲述线程池的基本知识,而是在做爬虫项目实际情况,碰到技术解决方案,简单的线程隔离的实践,在做爬虫时,会碰到反应慢和反应快的各种网站,如何同时用一个线程池去做爬虫请求,慢的网站会堵塞快的网站请求,这是就考虑线程隔离。线程池基于newFixedThreadPool()创建。

本文部分描述性内容来源于网络,其中示例性Java源代码经过本人亲自测试,如有不当、错误或侵权行为敬请指正。

 基于下图:

ps:这小伙只是提供具体实现方案,没看到具体代码,只能自己实现了!

 

实现功能:

 DynamicAsyncTaskService.java

 

/**  * 动态线程池  * @author wuche  * @version 暂时固定写死的,后期可以改造成基于spring建实例模式,或者基于懒加载模式创建  */ public class DynamicAsyncTaskService {  	private static DynamicAsyncTaskService service; 	//最大线程数(可以放使用多个) 	public static int executorPoolSize =10; 	//最大线程数(可以放少的) 	public static int executorPoolSize2 =5; 	//线程前缀名 	public static String poolName ="1"; 	//线程前缀名 	public static String poolName2 ="2"; 	private  ThreadPoolExecutor pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(executorPoolSize, setThreadFactory(poolName)); 	private  ThreadPoolExecutor pool2 = (ThreadPoolExecutor) Executors.newFixedThreadPool(executorPoolSize2, setThreadFactory(poolName2)); 	public static DynamicAsyncTaskService getInstance() { 		if (service == null) { 			service = new DynamicAsyncTaskService(); 		} 		return service; 	}     private ThreadFactory setThreadFactory(String poolName){     	return new DefaultThreadFactory(poolName);     }          private ThreadPoolExecutor getPool(int i){     	ThreadPoolExecutor newPool=null;     	if(i==1){     		newPool=pool;     	}else{     		newPool=pool2;     	}     	return newPool;     }          private int getPoolSize(int i){ 		int poolSize=executorPoolSize; 		if(i==1){ 			poolSize=executorPoolSize; 		}else{ 			poolSize=executorPoolSize2; 		} 		return poolSize; 	}     /**      * 获取可以使用线程数      * @param i      * @return      */ 	public int getAvailableNum(int i) { 		return getPoolSize(i)-getPool(i).getActiveCount(); 	} 	 	/** 	 * 获取活动线程数 	 * @param i 	 * @return 	 */ 	public int getActiveNum(int i) { 		return getPool(i).getPoolSize(); 	} 	/** 	 * 正在排队的线程数 	 * @return 	 */ 	public int getQueueNum(int i) { 		return getPool(i).getQueue().size(); 	} 	 	public void execute(Runnable command,int i) { 		getPool(i).execute(command); 	} 	 	@SuppressWarnings({ "rawtypes", "unchecked" }) 	public Future submit(Callable task,int i) { 		return getPool(i).submit(task); 	}  	@SuppressWarnings("rawtypes") 	public Future submit(Runnable task, Object result,int i) { 		return getPool(i).submit(task, result); 	} 	 	/** 	 * 自定义的ThreadFactory,便于日志打印 	 * @author wuche 	 * 	 */ 	static class DefaultThreadFactory implements ThreadFactory {   	    private static final AtomicInteger poolNumber = new AtomicInteger(1);   	    private final ThreadGroup group;   	    private final AtomicInteger threadNumber = new AtomicInteger(1);   	    private String namePrefix;   	   	    DefaultThreadFactory(String poolName) {   	        SecurityManager s = System.getSecurityManager();   	        group = (s != null) ? s.getThreadGroup() :  Thread.currentThread().getThreadGroup();   	        namePrefix = "pool"+poolName +"-"+  poolNumber.getAndIncrement() +  "-thread-";   	    }   	    // 为线程池创建新的任务执行线程   	    public Thread newThread(Runnable r) {  	        // 线程对应的任务是Runnable对象r   	        Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(), 0);   	        // 设为非守护线程   	        if (t.isDaemon())   	            t.setDaemon(false);   	        // 将优先级设为Thread.NORM_PRIORITY   	        if (t.getPriority() != Thread.NORM_PRIORITY)   	            t.setPriority(Thread.NORM_PRIORITY);   	        return t;   	    } 		public String getNamePrefix() { 			return namePrefix; 		} 		public void setNamePrefix(String namePrefix) { 			this.namePrefix = namePrefix; 		}   	     	}  }

测试类:TestAsyncTask.java

 

 

package com.haohan.thread;   public class TestAsyncTask { 	public static void main(String[] args){         for (int i = 0; i < 35; i++) {         	final long startTime=System.currentTimeMillis();         	if(i%2==0){         		System.out.println("线程一开始::---");         		DynamicAsyncTaskService.getInstance().execute(new Runnable() {                     @Override                     public void run() {                         try {                         	System.out.println("正在运行线程名字:"+Thread.currentThread().getName());                         	 System.out.println("线程池中现在的线程数目是:"+DynamicAsyncTaskService.getInstance().getActiveNum(1)+",队列中正在等待执行的任务数量为:"+ DynamicAsyncTaskService.getInstance().getQueueNum(1)                                 		+",可利用的线程数目:"+DynamicAsyncTaskService.getInstance().getAvailableNum(1)                                 		);                             Thread.currentThread().sleep(1000);                             long endTime=System.currentTimeMillis();                             System.out.println(Thread.currentThread().getName()+"结束时间"+(endTime-startTime));                             System.out.println("线程池中现在的线程数目是:"+DynamicAsyncTaskService.getInstance().getActiveNum(1)+",队列中正在等待执行的任务数量为:"+ DynamicAsyncTaskService.getInstance().getQueueNum(1)                              		+",可利用的线程数目:"+DynamicAsyncTaskService.getInstance().getAvailableNum(1)                              		);                         } catch (InterruptedException e) {                             e.printStackTrace();                         }                     }                 },1);         	}else{         		DynamicAsyncTaskService.getInstance().execute(new Runnable() {                     @Override                     public void run() {                         try {                         	System.out.println("正在运行线程名字:"+Thread.currentThread().getName());                         	 System.out.println("线程池中现在的线程数目2是:"+DynamicAsyncTaskService.getInstance().getActiveNum(2)+",队列中正在等待执行的任务2数量为:"+ DynamicAsyncTaskService.getInstance().getQueueNum(2)                                 		+",可利用的线程2数目:"+DynamicAsyncTaskService.getInstance().getAvailableNum(2)                                 		);                             Thread.currentThread().sleep(1000);                             long endTime=System.currentTimeMillis();                             System.out.println(Thread.currentThread().getName()+"结束时间"+(endTime-startTime));                             System.out.println("线程池中现在的线程数目是:"+DynamicAsyncTaskService.getInstance().getActiveNum(1)+",队列中正在等待执行的任务数量为:"+ DynamicAsyncTaskService.getInstance().getQueueNum(1)                              		+",可利用的线程数目:"+DynamicAsyncTaskService.getInstance().getAvailableNum(1)                              		);                         } catch (InterruptedException e) {                             e.printStackTrace();                         }                     }                 },2);         		           	}                   } 		 		/*System.out.println(Runtime.getRuntime().availableProcessors());*/     } }


测试结果:

 

 

线程一开始::--- 正在运行线程名字:pool1-1-thread-1 线程池中现在的线程数目是:1,队列中正在等待执行的任务数量为:0,可利用的线程数目:9 线程一开始::--- 正在运行线程名字:pool2-2-thread-1 线程池中现在的线程数目2是:1,队列中正在等待执行的任务2数量为:0,可利用的线程2数目:4 正在运行线程名字:pool1-1-thread-2 线程池中现在的线程数目是:2,队列中正在等待执行的任务数量为:0,可利用的线程数目:8 线程一开始::--- 正在运行线程名字:pool2-2-thread-2 线程池中现在的线程数目2是:2,队列中正在等待执行的任务2数量为:0,可利用的线程2数目:3 正在运行线程名字:pool1-1-thread-3 线程池中现在的线程数目是:3,队列中正在等待执行的任务数量为:0,可利用的线程数目:7 线程一开始::--- 正在运行线程名字:pool2-2-thread-3 线程池中现在的线程数目2是:3,队列中正在等待执行的任务2数量为:0,可利用的线程2数目:2 线程一开始::--- 正在运行线程名字:pool2-2-thread-4 线程池中现在的线程数目2是:4,队列中正在等待执行的任务2数量为:0,可利用的线程2数目:1 线程一开始::--- 正在运行线程名字:pool1-1-thread-5 线程池中现在的线程数目是:6,队列中正在等待执行的任务数量为:0,可利用的线程数目:4 正在运行线程名字:pool1-1-thread-4 线程池中现在的线程数目是:6,队列中正在等待执行的任务数量为:0,可利用的线程数目:4 正在运行线程名字:pool2-2-thread-5 线程池中现在的线程数目2是:5,队列中正在等待执行的任务2数量为:1,可利用的线程2数目:0 线程一开始::--- 正在运行线程名字:pool1-1-thread-6 线程池中现在的线程数目是:7,队列中正在等待执行的任务数量为:0,可利用的线程数目:3 线程一开始::--- 正在运行线程名字:pool1-1-thread-7 线程池中现在的线程数目是:8,队列中正在等待执行的任务数量为:0,可利用的线程数目:2 线程一开始::--- 线程一开始::--- 正在运行线程名字:pool1-1-thread-9 线程一开始::--- 正在运行线程名字:pool1-1-thread-8 线程一开始::--- 线程一开始::--- 线程一开始::--- 线程一开始::--- 线程一开始::--- 线程一开始::--- 线程一开始::--- 正在运行线程名字:pool1-1-thread-10 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:8,可利用的线程数目:0 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:0 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:1,可利用的线程数目:0 pool1-1-thread-1结束时间1008 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:8,可利用的线程数目:0 正在运行线程名字:pool1-1-thread-1 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:7,可利用的线程数目:0 pool1-1-thread-2结束时间1000 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:7,可利用的线程数目:0 正在运行线程名字:pool1-1-thread-2 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:6,可利用的线程数目:0 pool2-2-thread-1结束时间1010 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:6,可利用的线程数目:0 正在运行线程名字:pool2-2-thread-1 线程池中现在的线程数目2是:5,队列中正在等待执行的任务2数量为:11,可利用的线程2数目:0 pool2-2-thread-3结束时间1000 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:6,可利用的线程数目:0 正在运行线程名字:pool2-2-thread-3 线程池中现在的线程数目2是:5,队列中正在等待执行的任务2数量为:10,可利用的线程2数目:0 pool2-2-thread-2结束时间1001 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:6,可利用的线程数目:0 正在运行线程名字:pool2-2-thread-2 线程池中现在的线程数目2是:5,队列中正在等待执行的任务2数量为:9,可利用的线程2数目:0 pool1-1-thread-3结束时间1002 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:6,可利用的线程数目:0 正在运行线程名字:pool1-1-thread-3 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:5,可利用的线程数目:0 pool2-2-thread-4结束时间1001 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:5,可利用的线程数目:0 正在运行线程名字:pool2-2-thread-4 线程池中现在的线程数目2是:5,队列中正在等待执行的任务2数量为:8,可利用的线程2数目:0 pool2-2-thread-5结束时间1001 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:5,可利用的线程数目:0 正在运行线程名字:pool2-2-thread-5 线程池中现在的线程数目2是:5,队列中正在等待执行的任务2数量为:7,可利用的线程2数目:0 pool1-1-thread-4结束时间1002 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:5,可利用的线程数目:0 正在运行线程名字:pool1-1-thread-4 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:4,可利用的线程数目:0 pool1-1-thread-6结束时间1002 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:4,可利用的线程数目:0 正在运行线程名字:pool1-1-thread-6 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:3,可利用的线程数目:0 pool1-1-thread-9结束时间1003 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:3,可利用的线程数目:0 正在运行线程名字:pool1-1-thread-9 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:2,可利用的线程数目:0 pool1-1-thread-10结束时间1003 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:2,可利用的线程数目:0 正在运行线程名字:pool1-1-thread-10 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:1,可利用的线程数目:0 pool1-1-thread-7结束时间1005 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:1,可利用的线程数目:0 正在运行线程名字:pool1-1-thread-7 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:0 pool1-1-thread-8结束时间1005 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:0 pool1-1-thread-5结束时间1007 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:1 pool1-1-thread-1结束时间1987 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:2 pool2-2-thread-1结束时间1997 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:3 正在运行线程名字:pool2-2-thread-1 线程池中现在的线程数目2是:5,队列中正在等待执行的任务2数量为:6,可利用的线程2数目:0 pool1-1-thread-2结束时间1996 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:3 pool2-2-thread-3结束时间1997 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:4 正在运行线程名字:pool2-2-thread-3 线程池中现在的线程数目2是:5,队列中正在等待执行的任务2数量为:5,可利用的线程2数目:0 pool1-1-thread-4结束时间2001 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:4 pool2-2-thread-5结束时间2001 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:5 正在运行线程名字:pool2-2-thread-5 线程池中现在的线程数目2是:5,队列中正在等待执行的任务2数量为:4,可利用的线程2数目:0 pool2-2-thread-2结束时间2003 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:5 正在运行线程名字:pool2-2-thread-2 线程池中现在的线程数目2是:5,队列中正在等待执行的任务2数量为:3,可利用的线程2数目:0 pool1-1-thread-3结束时间2003 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:5 pool2-2-thread-4结束时间2003 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:6 正在运行线程名字:pool2-2-thread-4 线程池中现在的线程数目2是:5,队列中正在等待执行的任务2数量为:2,可利用的线程2数目:0 pool1-1-thread-6结束时间2003 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:6 pool1-1-thread-9结束时间2003 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:7 pool1-1-thread-10结束时间2004 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:8 pool1-1-thread-7结束时间2005 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:9 pool2-2-thread-1结束时间2996 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:10 正在运行线程名字:pool2-2-thread-1 线程池中现在的线程数目2是:5,队列中正在等待执行的任务2数量为:1,可利用的线程2数目:0 pool2-2-thread-3结束时间2997 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:10 正在运行线程名字:pool2-2-thread-3 线程池中现在的线程数目2是:5,队列中正在等待执行的任务2数量为:0,可利用的线程2数目:0 pool2-2-thread-5结束时间3001 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:10 pool2-2-thread-4结束时间3003 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:10 pool2-2-thread-2结束时间3003 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:10 pool2-2-thread-1结束时间3996 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:10 pool2-2-thread-3结束时间3997 线程池中现在的线程数目是:10,队列中正在等待执行的任务数量为:0,可利用的线程数目:10


从以上结果可以看出,newFixedThreadPool的参数指定了可以运行的线程的最大数目,超过这个数目的线程加进去以后,不会立即运行,而是被放入任务队列中等待执行。其次,加入线程池的线程属于托管状态,线程的运行不受加入顺序的影响。并且两个线程池是不会相互影响的!

 

该场景可以用到需要多线程业务当中是没问题的!!
 

本文发表于2017年10月24日 20:34
(c)注:本文转载自https://my.oschina.net/u/2241980/blog/1555637,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1609 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1