背景
本文不是讲述线程池的基本知识,而是在做爬虫项目实际情况,碰到技术解决方案,简单的线程隔离的实践,在做爬虫时,会碰到反应慢和反应快的各种网站,如何同时用一个线程池去做爬虫请求,慢的网站会堵塞快的网站请求,这是就考虑线程隔离。线程池基于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
该场景可以用到需要多线程业务当中是没问题的!!