VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > 简明python教程 >
  • 简单看看ThreadPoolExecutor原理(6)

设置所有空闲线程的中断标志 private void interruptIdleWorkers() { interruptIdleWorkers(false); } private void interruptIdleWorkers(boolean onlyOne) { //加锁,同时只有一个线程可以调用shutdown方法设置中断标志 final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { //遍历所有的worker中的线程,如果线程没有中断然后成功获取worker自己的锁,就中断该线程 //注意,worker实现了AQS,如果worker能够获取自己的锁,说明该线程没有在执行任务,就可以设置中断 //而有的worker中的线程正在执行的任务的线程,则不会中断 for (Worker w : workers) { Thread t = w.thread; if (!t.isInterrupted() && w.tryLock()) { try { t.interrupt(); } catch (SecurityException ignore) { } finally { w.unlock(); } } if (onlyOne) break; } } finally { mainLock.unlock(); } }
复制代码

 

六.shutdownNow方法

  这个方法和shutdown的区别就是,前者会中断线程池中所有的线程,不管是正在执行任务的还是空闲的,而且还会把阻塞队列中没来得及执行的任务丢弃;

复制代码
public List<Runnable> shutdownNow() {
    List<Runnable> tasks;
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        //权限检查
        checkShutdownAccess();
        //将线程池状态设置为STOP
        advanceRunState(STOP);
        //中断线程池中所有线程
        interruptWorkers();
        //将阻塞队列中任务都抛弃
        tasks = drainQueue();
    } finally {
        mainLock.unlock();
    }
    tryTerminate();
    return tasks;
}

 //中断线程池中所有线程
private void interruptWorkers() {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        //这里直接遍历,所有的worker都调用interruptIfStarted方法,这个方法就在下面
        for (Worker w : workers)
            w.interruptIfStarted();
    } finally {
        mainLock.unlock();
    }
}
void interruptIfStarted() {
    Thread t;
    //如果Worker的线程不为空,而且该线程不是中断状态,就把该线程中断
    if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
        try {
            t.interrupt();
        } catch (SecurityException ignore) {
        }
    }
}


//将阻塞队列中任务都抛弃,很简单的集合操作
private List<Runnable> drainQueue() {
    BlockingQueue<Runnable> q = workQueue;
    ArrayList<Runnable> taskList = new ArrayList<Runnable>();
    q.drainTo(taskList);
    if (!q.isEmpty()) {
        for (Runnable r : q.toArray(new Runnable[0])) {
            if (q.remove(r))
                taskList.add(r);
        }
    }
    return taskList;
}
复制代码

  

七.总结

  重要的方法就是这几个,其实所谓的线程池就是巧妙的利用了一个Integer类型的原子变量来记录线程池状态和线程池中线程数量,通过线程池状态来控制线程的执行,每个Worker线程可以执行多个任务,其实就是在runWorker中的循环:while (task != null || (task = getTask()) != null) ,在这里不断的轮询拿到当前Worker中的第一个任务或者从任务队列中取到任务,然后会去执行;

 


相关教程
          
关于我们--广告服务--免责声明--本站帮助-友情链接--版权声明--联系我们       黑ICP备07002182号