Java线程池
数据仓库在任务调度过程中,需要控制和监控数据的下载,加载,清洗等过程,其中用线程池来管理。
1 public class ThreadPool extends ThreadPoolExecutor { 2 3 private static final Logger logger = LoggerFactory 4 .getLogger(ThreadPool.class); 5 private TaskPuller getter; 6 private AtomicBoolean isStop; 7 private Thread getterThread; 8 private int capacity; 9 Map<Integer,Thread> map; 10 /** Lock held by put, offer, etc */ 11 private final ReentrantLock putLock = new ReentrantLock(); 12 13 /** Wait queue for waiting puts */ 14 private final Condition full = putLock.newCondition(); 15 private AtomicInteger count; 16 17 public ThreadPool(int size,TaskPuller getter) { 18 super(size, size, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(size)); 19 map=new ConcurrentHashMap<Integer,Thread>(); 20 capacity=2*size; 21 count=new AtomicInteger(0); 22 isStop=new AtomicBoolean(true); 23 this.getter=getter; 24 run();//启动任务获取线程 25 } 26 }
查看源码,发现ThreadPoolExecutor继承AbstractExecutorService,AbstractExecutorService实现ExecutorService接口,ExecutorService接口继承Executor,Executor是顶层接口,只有一个void execute(Runnable command);的execute方法。
查看ThreadPoolExecutor的主要实现类,主要有如下几个比较重要的成员变量。
private final BlockingQueue<Runnable> workQueue; private final ReentrantLock mainLock = new ReentrantLock();
private volatile ThreadFactory threadFactory; private volatile RejectedExecutionHandler handler; private volatile long keepAliveTime; private volatile int corePoolSize; private volatile int maximumPoolSize;
workQueue是存放等待执行的任务队列,mainLock是用来判断线程池主要执行状态的锁,threadFactory是用来创建线程的工厂,handler是用来处理任务超出最大限制时候的策略,keepAliveTime是线程空闲存活时间,corePoolSize是线程池核心数量,maximumPoolSize是线程池最大数量。
查看ThreadPoolExecutor的主要execute方法。
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); else if (workerCountOf(recheck) == 0) addWorker(null, false); } else if (!addWorker(command, false)) reject(command); }
如果当前工作线程总数小于线程池核心数量,把当前命令加入到工作线程队列中。通过2次检查AtomicInteger型ctl的状态,来判断是否需要回滚操作,还有0值处理。如果添加到工作队列失败,按照拒绝策略来拒绝当前命令。
private void run(){ getterThread=new Thread(new Runnable() { public void run() { while(isStop.get()){ List<ETLTask> tasks=getter.getTasks(); for (ETLTask task : tasks) { if(!isStop.get()) return; try{ task.readyToExecute(); } catch (Exception e) { logger.error("try to update task status to wait executing failed: "+task.toString()); continue; } execute(task); logger.debug("add task to thread pool successed: "+task.toString()); } } } }); getterThread.start(); } }
在初始化线程池之后,调用run方法来执行任务。通过AtomicBoolean的原子型变量isStop的值,用while轮询任务,来控制任务执行的开闭。
最后在execute方法和afterExecute方法中,使用condition实现线程的等待和通知。如果当前线程总数已满,把当前线程加入等待队列中。执行完一个线程后,唤醒一个在等待队列中的线程来执行。
public void execute(Runnable r){ if(!isStop.get()) return; ETLTask task=(ETLTask)r; try { putLock.lockInterruptibly(); while(count.get()==capacity-1){ full.await(); } count.getAndIncrement(); super.execute(r); } catch (InterruptedException e1) { logger.error("get the lock failed during add the task to the threadpool's task queue because of interupting",e1 ); }catch(RejectedExecutionException e2){ logger.error("add the task to the threadpool's task queue failed",e2); } finally { putLock.unlock(); } } public void afterExecute(Runnable r, Throwable t) { int c=-1; map.remove(r); try { putLock.lockInterruptibly(); c=count.decrementAndGet(); if(c<capacity) full.signal(); } catch (InterruptedException e) { logger.error("decrement the task count failed when get the lock" ,e); } finally{ putLock.unlock(); } }
posted on 2018-12-23 19:20 OneLi算法分享社区 阅读(122) 评论(0) 编辑 收藏 举报