zoukankan      html  css  js  c++  java
  • 线程池

    1.sleep 与 wait 的区别

    sleep不会让出锁,而wait会让出锁.

    2.调用线程的interrupt方法,即使线程wait或者sleep也能感知到,并抛出异常

    3.线程的6种状态,

    1. New(新创建) 

    2. Runnable(可运行)

    3. Blocked(被阻塞)

    4. Waiting(等待)

    5. Timed Waiting(计时等待)

    6. Terminated(被终止)

    block是指在进入synchronize修饰的方法没有获得monitor锁

    waiting是指调用wait/join/LockSupport.park

    Timed Witing:线程调用sleep方法

    4.线程池

    刚开始随着任务的进来,线程池会创建核心线程来执行,当创建到corePoolSize之后,任务就会被存放到工作队列里面。当工作队列满了的时候,就又会创建线程直到maxPoolSize。如果队列还是满了的话,就会执行拒绝策略.

    线程池的实现原理

    首先,线程池中用一个AtomicInteger的高三位来表示状态位,低29位来表示线程的数量

    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    
    // 这里 COUNT_BITS 设置为 29(32-3),意味着前三位用于存放线程状态,后29位用于存放线程数
    // 很多初学者很喜欢在自己的代码中写很多 29 这种数字,或者某个特殊的字符串,然后分布在各个地方,这是非常糟糕的
    private static final int COUNT_BITS = Integer.SIZE - 3;
    
    // 000 11111111111111111111111111111
    // 这里得到的是 29 个 1,也就是说线程池的最大线程数是 2^29-1=536870911
    // 以我们现在计算机的实际情况,这个数量还是够用的
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
    
    // 我们说了,线程池的状态存放在高 3 位中
    // 运算结果为 111跟29个0:111 00000000000000000000000000000
    private static final int RUNNING    = -1 << COUNT_BITS;
    // 000 00000000000000000000000000000
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    // 001 00000000000000000000000000000
    private static final int STOP       =  1 << COUNT_BITS;
    // 010 00000000000000000000000000000
    private static final int TIDYING    =  2 << COUNT_BITS;
    // 011 00000000000000000000000000000
    private static final int TERMINATED =  3 << COUNT_BITS;
    
    // 将整数 c 的低 29 位修改为 0,就得到了线程池的状态
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
    // 将整数 c 的高 3 为修改为 0,就得到了线程池中的线程数
    private static int workerCountOf(int c)  { return c & CAPACITY; }
    
    private static int ctlOf(int rs, int wc) { return rs | wc; }
    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);
        }
     private boolean addWorker(Runnable firstTask, boolean core) {
            retry:
            for (;;) {
                int c = ctl.get();
                int rs = runStateOf(c);
    
                // Check if queue empty only if necessary.
                if (rs >= SHUTDOWN &&
                    ! (rs == SHUTDOWN &&
                       firstTask == null &&
                       ! workQueue.isEmpty()))
                    return false;
    
                for (;;) {
                    int wc = workerCountOf(c);
                    if (wc >= CAPACITY ||
                        wc >= (core ? corePoolSize : maximumPoolSize))
                        return false;
                    if (compareAndIncrementWorkerCount(c))
                        break retry;
                    c = ctl.get();  // Re-read ctl
                    if (runStateOf(c) != rs)
                        continue retry;
                    // else CAS failed due to workerCount change; retry inner loop
                }
            }
    
            boolean workerStarted = false;
            boolean workerAdded = false;
            Worker w = null;
            try {
                w = new Worker(firstTask); //Worker对象实现了Runnable方法,在构造函数中线程工厂创建线程,worker对象本身作为参数.
                final Thread t = w.thread;
                if (t != null) {
                    final ReentrantLock mainLock = this.mainLock;
                    mainLock.lock();
                    try {
                        // Recheck while holding lock.
                        // Back out on ThreadFactory failure or if
                        // shut down before lock acquired.
                        int rs = runStateOf(ctl.get());
    
                        if (rs < SHUTDOWN ||
                            (rs == SHUTDOWN && firstTask == null)) {
                            if (t.isAlive()) // precheck that t is startable
                                throw new IllegalThreadStateException();
                            workers.add(w);
                            int s = workers.size();
                            if (s > largestPoolSize)
                                largestPoolSize = s;
                            workerAdded = true;
                        }
                    } finally {
                        mainLock.unlock();
                    }
                    if (workerAdded) {
                        t.start();//就是调用了Worker对象的run方法()
                        workerStarted = true;
                    }
                }
            } finally {
                if (! workerStarted)
                    addWorkerFailed(w);
            }
            return workerStarted;
        }
    public void run() {
                runWorker(this);
            }
    final void runWorker(Worker w) {
            Thread wt = Thread.currentThread();
            Runnable task = w.firstTask; //传入的任务
            w.firstTask = null;
            w.unlock(); // allow interrupts
            boolean completedAbruptly = true;
            try {
                while (task != null || (task = getTask()) != null) {//线程在这里循环工作,从阻塞队列中拿出任务
                    w.lock();
                    // If pool is stopping, ensure thread is interrupted;
                    // if not, ensure thread is not interrupted.  This
                    // requires a recheck in second case to deal with
                    // shutdownNow race while clearing interrupt
                    if ((runStateAtLeast(ctl.get(), STOP) ||
                         (Thread.interrupted() &&
                          runStateAtLeast(ctl.get(), STOP))) &&
                        !wt.isInterrupted())
                        wt.interrupt();
                    try {
                        beforeExecute(wt, task);
                        Throwable thrown = null;
                        try {
                            task.run();//直接调用run方法,
                        } catch (RuntimeException x) {
                            thrown = x; throw x;
                        } catch (Error x) {
                            thrown = x; throw x;
                        } catch (Throwable x) {
                            thrown = x; throw new Error(x);
                        } finally {
                            afterExecute(task, thrown);
                        }
                    } finally {
                        task = null;
                        w.completedTasks++;
                        w.unlock();
                    }
                }
                completedAbruptly = false;
            } finally {
                processWorkerExit(w, completedAbruptly);
            }
        }
     
  • 相关阅读:
    ini_set /ini_get函数功能-----PHP
    【转】那个什么都懂的家伙
    word 2007为不同页插入不同页眉页脚
    August 26th 2017 Week 34th Saturday
    【2017-11-08】Linux与openCV:opencv版本查看及库文件位置等
    August 25th 2017 Week 34th Friday
    August 24th 2017 Week 34th Thursday
    August 23rd 2017 Week 34th Wednesday
    August 22nd 2017 Week 34th Tuesday
    August 21st 2017 Week 34th Monday
  • 原文地址:https://www.cnblogs.com/lzh66/p/13221872.html
Copyright © 2011-2022 走看看