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

背景

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

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


   基于下图:

多线程池newFixedThreadPool之动态多线程池做线程池隔离_第1张图片

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

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


你可能感兴趣的:(java,并发)