线程多线程总结

时间:2021-06-03 04:33:36

 纯属个人的理解,还请各位牛人多多指教。线程多线程总结

 
线程的基本概念:
    先看进程的基本概念:计算机中正在运行的程序,包含有进程控制块和程序所需要的系统资源
    线程:进程中的一条执行路径,没有独立的系统资源,共享进程的资源,但是能够含有自己的栈区
    java中的线程运行模型:
    每一个程序都有自己的主内存,而每一个线程都有自己的工作内存(寄存器和缓存)。
     当开始了一个线程之后,线程需要到了某一共享变量,先把它拷贝到自己的工作内存当中,
    然后进行使用,赋值之后还会把它写回到主内存当中。一般来说当赋值之后就会把这个共享变量写回主内存,但是这一个过程
   并不是原子性的,也就是说当我们对变量的值进行改变的时候,还没有来的及把它的新值写回时,另一个线程也访问了这个共享变量
   这 就导致了读取错误。例如:本来是1000元 a线程读取后加100,没有写回时,b线程读取,还是1000这是进行其他的操作就使得结果并不正确

   volatile:变量的引入就是为了解决这个问题,但是会影响一定的性能。它意思时可见的。当我们为一个共享变量(其实很多时候就时成员变量)使用了该
   关键字,说明当我们对这个变量进行了改变之后立马就会写回主内存,这个操作是原子的不能分割的。
   另一个机制--同步机制
   线程安全:就是当我们访问同一块代码时不会产生不同的结果。线程不安全则相反。
   同步:就是指某一块代码能够按照某一调度机制进行执行,来保证线程安全yu
   银行取款问题,就是典型的同步问题。
   描述:进行取款时要判断余额,当多个账号进行去的时候(也就是多个线程)就会出现负值的情况
线程多线程总结


 上图就是线程的状态变化(有点丑)。
需要重点聊聊阻塞队列(block):现在我理解的程度可以理解了大致有三个
1.普通block:当一个线程sleep()和join()时进入该队列。等到时间等待时间结束后就进入就绪对列等待运行
2.等待block:我喜欢把它叫做等待池,当一个线程wait()时就入该队列。唤醒之后就锁定队列
3.锁定block:我把它称为锁定池。当一个线程获取同步锁失败时就会进入该队列,当它获取到同步锁后进入就绪队列。  

  对于每一个对象中关于线程机制的理解以及常用方法:
  1.在每一个对象中都会有一个monitor监视器。当调用wait()就会将当前线程添加到等待池中,并且由该监视器 (同步锁的) 进行监视掌管。
  执行notify(),notifyall()时就会唤醒该监视器所掌管的线程,使其进入锁定池中,当获取到锁时进入就绪队列等待执行。
  另外wait()和notify notifyall方法只能出现在同步代码块中。这也很好理解,因为使用这些方法是需要monitor进行监视。
 2. Thread.sleep(long)使的当前线程睡眠,进入普通锁定池中。和wait()最主要的区别使它不释放同步锁,以及它在任何地方都可以调用
 3.t.join():字面理解是合并的意思,其实就是当前线程等待调用这个方法的线程执行完毕。
 4.t.interrupt():调用这个方法的线程,如果处于wait() sleep() join()时就会中断该线程,中断异常
 5.t.setDaemon(true)设置为守护线程,简单的理解其实就是当其他的线程全部执行终止之后,守护线程才终止。JVM的垃圾回收就是一个守护线程。调用main方法的也是
   一个守护线程。
 6.t.setPriority()设置优先级。取值为(0到10)会对抢占cpu起到一定的作用
下面是一个简单的例子:(理解了上述的方法之后自己写一个完整的例子)
public class ThreadTestFun {
      public static void main(String[] args ) {
           // TODO Auto-generated method stub
          Thread t1 = new Thread( new thread1());
          Thread t2 = new Thread( new thread2(Thread.currentThread()));
           t1 .start();
           t2 .start();
           t1 .setPriority(10);
           try {
               t1 .join();
               t1 .yield();
          } catch (InterruptedException e ) {
               // TODO Auto-generated catch block
               e .printStackTrace();
          }
     }
}
class thread1 implements Runnable {
      @Override
      public void run() {
           // TODO Auto-generated method stub
           /*
           * try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO
           * Auto-generated catch block e.printStackTrace(); }
           */
           // synchronized (this) {
           // try {
           // wait();
           // } catch (InterruptedException e) {
           // // TODO Auto-generated catch block
           // e.printStackTrace();
           // }
           // }
           while ( true ) {
              notify();
              notifyAll();
          }
     }
}
class thread2 implements Runnable {
     Thread thread ;
      public thread2(Thread thread ) {
           super ();
           this . thread = thread ;
     }
      @Override
      public void run() {
           // TODO Auto-generated method stub
           try {
              Thread.sleep(1000);
          } catch (InterruptedException e ) {
               // TODO Auto-generated
               e .printStackTrace();
          }
           // synchronized (this) {
           // try {
           // wait();
           // } catch (InterruptedException e) {
           // // TODO Auto-generated catch block
           // e.printStackTrace();
           // }
           // }
           thread .interrupt();
     }
}
线程实现的方式:
   线程实现的基本方式有三种:
   1.继承Thread  
     class MyThread extends Thread{
          //重写run
          public void run(){
          } 
     }
     public static void main(String[] args ) {
           // TODO Auto-generated method stub
          Thread t1 = new   MyThread ( );

           t1 .start();
      }
  2.实现Runnable接口
      public static void main(String[] args ) {
           // TODO Auto-generated method stub
          Thread t1 = new Thread( new thread1());

           t1 .start();
     }
}
class thread1 implements Runnable {
      @Override
      public void run() {
     }
}
3.匿名内部类实现
  
  public static void main(String[] args ) {
           // TODO Auto-generated method stub
          Thread t1 = new Thread(new Runnable(){
           
     @Override
      public void run() {
     }
      } );

           t1 .start();
     }
线程间的通信:
  1.通过构造方法
  2.使用wait()和notify notifyAll(),当某一个条件不满足时,线程等待,满足时唤醒。著名的生产者消费者问题
  
//实现线程之间的通信,模仿生产者和消费者 使用wait notify实现
public class ThreadChat {
      public static void main(String[] args ) {
           // TODO Auto-generated method stub
          Production pro = new Production();
          Productor por = new Productor( pro );
          Constumer con = new Constumer( pro );
           new Thread( por ).start();
           new Thread( con ).start();
          
     }
}
// 生产者和消费者问题:就是由生产者生产商品,消费者进行消费。需要注意的问题是当商品没有的时候是不能消费的,商品满的
// 时候是不能消费的。
// 多生产者和多消费者问题:需要注意的是同步问题,例如当只有一个商品的时候,消费者一进行了消费,消费者二也进行了消费
// 这就存在了问题。
class Production {
      int [] production = new int [10];
      int p = -1; // 用来指向当前的商品
      public synchronized void product() {
           // 先判断商品的个数 说明已经满了 不能生产 等待
           if ( p == ( production . length - 1)) {
               try {
                   wait();
              } catch (InterruptedException e ) {
                    // TODO Auto-generated catch block
                    e .printStackTrace();
              }
          }
           production [++ p ] = 1;
          System. out .println(Thread.currentThread().getName() + "生产了" + p );
           // 当没有商品是消费者会进入等待状态需要被唤醒
           // notify(); 只能唤醒一个消费者
          notifyAll();
     }
      public synchronized void consum() {
           // 先判断商品的个数 说明已经没了 不能消费 等待
           if ( p == -1) {
               try {
                   wait();
              } catch (InterruptedException e ) {
                    // TODO Auto-generated catch block
                    e .printStackTrace();
              }
          }
           production [ p --] = 0;
          System. out .println(Thread.currentThread().getName() + "消费了" + ( p + 1));
           // 当商品满时 生产者会进入等待状态需要被唤醒
           // notify(); 只能唤醒一个生产者
          notifyAll();
     }
}
class Productor implements Runnable {
     Production pro ;
      public Productor(Production pro ) {
           super ();
           this . pro = pro ;
     }
      @Override
      public void run() {
           // TODO Auto-generated method stub
           int i = 0;
           while ( i < 20) {
               // pro.product();
               pro .product();
               i ++;
          }
     }

}
class Constumer implements Runnable {
     Production pro ;
      @Override
      public void run() {
           // TODO Auto-generated method stub
           int i = 0;
           while ( i < 20) {
               // pro.consum();
               pro .consum();
               i ++;
          }
     }
      public Constumer(Production pro ) {
           super ();
           this . pro = pro ;
     }
}
   3.使用 PipedInputStream PipedOutputStream 管道缓存流 import java.io.IOException;
//PipedInputStream PipedOutputStream 管道缓存流 用来进行线程之间的通信 带阻塞的管道流 不推荐在一个线程中同时使用
public class ThreadChat2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Stack stack = new Stack();
        Thread t1 = new Thread(new T1(stack));
        Thread t2 = new Thread(new T2(stack));

        t1.start();
        t2.start();
    }

}

class Stack {
    private PipedInputStream pis;
    private PipedOutputStream pos;

    public Stack() {
        super();
        pis = new PipedInputStream();
        pos = new PipedOutputStream();
        try {
            pos.connect(pis);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void push(int i) {
        try {
            pos.write(i);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void pop() {
        try {
            System.out.println(pis.read());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

class T1 implements Runnable {
    Stack stack;

    public T1(Stack stack) {
        super();
        this.stack = stack;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 10; i++) {
            stack.push(i);
        }
    }

}

class T2 implements Runnable {
    Stack stack;

    public T2(Stack stack) {
        super();
        this.stack = stack;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 10; i++) {
            stack.pop();
        }
    }

}
     这是基本的三种
线程组:这里就简单的介绍一下。系统的每一个线程都有指定的线程组。如果没有指定,那么这个线程将会属于系统线程组,也就是main线程组
        也可以人为的指定。
   public class ThreadGroupTest {
      public static void main(String[] args ) {
           // TODO Auto-generated method stub
          demo1();
          ThreadGroup tg = new ThreadGroup( "我是新的线程池组" );
          MyRunnable mr = new MyRunnable();
          Thread t1 = new Thread( tg , mr , "张三" ); // 将线程t1放在组中
          Thread t2 = new Thread( tg , mr , "李四" );
          System. out .println( t1 .getThreadGroup().getName());
          System. out .println( t2 .getThreadGroup().getName());
     }
      public static void demo1() {
          MyRunnable mr = new MyRunnable();
          Thread t1 = new Thread( mr , "张三" );
          Thread t2 = new Thread( mr , "李四" );
          ThreadGroup tg1 = t1 .getThreadGroup();
          ThreadGroup tg2 = t2 .getThreadGroup();
          System. out .println( tg1 .getName()); // 默认的是主线程
          System. out .println( tg2 .getName());
     }
}
class MyRunnable implements Runnable {
      @Override
      public void run() {
           for ( int i = 0; i < 1000; i ++) {
               System. out .println(Thread.currentThread().getName() + "...." + i );
          }
     }
}
 
线程池:就是可以存放多个线程,根据一定的算法进行调度。
  简单使用
ExecutorService pool = Executors.newSingleThreadExecutor(); //创建单个线程
Executors.newFixedThreadPool(5); //创建指定个线程
pool.submit(Runnable task);  //执行任务
线程池问题的解决:
 用法: ThreadPoolExecutor pool = new ThreadPoolExecutor(......);
            pool.execute(Runnable task);
 常用的api有:execute();执行任务
                      shutdown();不会立即终止线程池,停止接收新的任务,等待缓存队列中的任务全部执行完毕后终止线程池
                      shutdownNow();立即终止线程池,同时尝试打断正在执行的任务。
                      allowCoreThreadTimeOut(boolean)允许线程池中的核心线程响应等待时间的设置,
                      就是当核心线程的空闲的时间超过创建线程池的设置的
                      时间,核心线程也会进行终止。
            pool.getCompletedTaskCount():拿到完成的任务的数量
            getCorePoolSize():拿到核心池的大小
            getPoolSize():拿到当前的线程数量
            getLargestPoolSize():拿到最近的线程池中曾经出现过的线程的最大的数量

 线程池的实现原理:

    - ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)
    - Creates a new ThreadPoolExecutor with the given initial parameters and default thread factory and rejected execution handler.

    - ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)
    - Creates a new ThreadPoolExecutor with the given initial parameters and default thread factory.

    - ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)
    - Creates a new ThreadPoolExecutor with the given initial parameters and default rejected execution handler.

    - ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
    - Creates a new ThreadPoolExecutor with the given initial parameters.
            参数解释:corePoolSize:线程池中的核心线程的数量。核心线程指的是在一般的情况下(缓存队列没有满的情况)线程池中所持有的线程。
                            在 默认的情况下,在刚刚建立线程池时,线程池中并没有线程。可以通过prestartAllCoreThreads()和prestartCoreThread()来
                            创建全部的核心线程或者一个核心线程。
                            maximumPoolSize:线程池中所允许的最大的线程数量。当核心线程都在执行任务并且此时缓存队列已满的情况下,当再次有任务时就会创建新的线程
                            当然线程的数量不能超过最大线程数
                            keepAliveTime:空闲等待时间,当一个线程空闲的时间超过了这个时间,这个线程就会终止。默认的前提的条件时当前的线程数量大于核心线程的数量
                            通过allowCoreThreadTimeOut(boolean)这个方法可设置为这个时间对核心线程同样有效
                            unit:是keepAliveTime的时间单位,可取值为TimeUnit.DAYS; //天   TimeUnit.HOURS;//小时   TimeUnit.MINUTES; //分钟    TimeUnit.SECONDS;//秒
                            TimeUnit.MILLISECONDS;//毫秒     TimeUnit.MICROSECONDS;//微秒     imeUnit.NANOSECONDS;//纳秒
                            workQueue:缓存队列,就是保存将要执行的任务.它有这么几种:
                             ArrayBlockingQueue; 使用数组的结构,先进先出的策略
                             SynchronousQueue;
                             LinkedBlockingQueue:使用链表的,先进先出的策略
                             threadFactory:线程工厂,用来创建线程,其实默认的实现就是 new Thread()了一下
                             handler:拒绝某一个线程时所采用的处理放式,线程池中的数量达到最大时,再次有任务时,就会产生拒绝。包含如下几种:
                             ThreadPoolExecutor.AbortPolicy:不执行当前任务,并且抛出异常
                             ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

                             ThreadPoolExecutor.DiscardOldestPolicy:丢弃缓存队列最前面的任务,尝试重新执行任务。能够重复执行此过程
                             ThreadPoolExecutor.DiscardPolicy:丢弃该任务,但是不抛出异常
            参数了解了之后就可以看看线程池的运行过程:当有任务来时,开启一个线程执行,当线程数达到核心池的大小时,任务进入缓冲队列,缓冲队列满的时候,就开劈新的线程,当线程数达到
           最大的线程数时,如果还有任务进来就抛出异常。
            我们可以看出前三个构造方法其实都在调用第四个构造方法。
            首先让我们看一下ThreadPoolExecutor的继承结构以及其中的部分源码
            public class ThreadPoolExecutor extends AbstractExecutorService{           
     // runState is stored in the high-order bits
             //代表线程池的运行状态
    private static final int RUNNING     = -1 << COUNT_BITS ;   //正在运行中
    private static final int SHUTDOWN    =  0 << COUNT_BITS ;   // shutdown()执行完线程池就会进入这个状态,线程池没有马上关闭,但是不接收新的任务
    private static final int STOP        =  1 << COUNT_BITS ;   //shutdownNow()执行之后进入,不接收新的任务,不执行任务队列中的任务,同时尝试终止正在执行的任务
    private static final int TIDYING     =  2 << COUNT_BITS ;   //当线程池为空同时缓存队列中没有了任务时,进入这个模式(我一般喜欢说成干净模式)
    private static final int TERMINATED =  3 << COUNT_BITS ;  //进入TIDYING模式之后,调用 terminated()方法之后进入终止模式,这个方法默认是一个空的实现,子类可以重写
         private final BlockingQueue<Runnable> workQueue ;  //缓存队列
    private final ReentrantLock mainLock = new ReentrantLock(); //线程池锁,在状态改变时使用(同一时刻只有一个线程能够改变线程池的状态)
    private final HashSet<Worker> workers = new HashSet<Worker>(); //work工作集,其实就是它充当了池的作用
    private int largestPoolSize ;  //最近线程池达到的最大的数量
    private long completedTaskCount ;//已经完成的任务数量
    private volatile ThreadFactory threadFactory ; //线程工厂
    private volatile RejectedExecutionHandler handler ; //拒绝任务时的处理策略 默认是AbortPolicy
    private volatile long keepAliveTime ; //空闲时间
    p rivate volatile boolean allowCoreThreadTimeOut ; //允许核心线程响应空闲时间,使其在空闲时间达到时进行终止
    private volatile int corePoolSize ; //核心线程的数量
    private volatile int maximumPoolSize ;//最大的线程数
    
     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 ))    //如果缓存队列也满了,那么就创建新的线程处理任务也就是worker 这个时候是以 maximumPoolSize为界限的
            reject( command );
    }

  //core 代表是否以 corePoolSize 为工作集的界限,否则 maximumPoolSize为界限
  private boolean addWorker(Runnable firstTask , boolean core ) {
        retry:
        for (;;) {
            int c = ctl .get();          
            int rs =runStateOf( c );     //拿到当前的运行状态
           
            if ( rs >= SHUTDOWN &&                  //当前状态为  STOP  TIDYING  TERMINATED   不运行向线程池中添加新的任务。当前状态为 SHUTDOWN firstTask为null
                ! ( rs == SHUTDOWN &&                缓存队列不为空时时可以向工作集中添加worker的
                   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;
            
            }
        }
        boolean workerStarted = false ;
        boolean workerAdded = false ;
        Worker w = null ;
        try {
            w = new Worker( firstTask );                          //根据任务创建工作者
            final Thread t = w . thread ;                           
            if ( t != null ) {
                final ReentrantLock mainLock = this . mainLock ;
                mainLock .lock();
                try {
                    
                    int rs =runStateOf( ctl .get());
                    if ( rs < SHUTDOWN ||
                        ( rs == SHUTDOWN && firstTask == null )) {
                        if ( t .isAlive())                             //这就是上文提到的措施 因为任务是空的,如果线程是运行的就抛异
                            throw new IllegalThreadStateException();
                        workers .add( w );
                        int s = workers .size();
                        if ( s > largestPoolSize )
                            largestPoolSize = s ;
                        workerAdded = true ;
                    }
                } finally {
                    mainLock .unlock();
                }
                if ( workerAdded ) {
                    t .start();     //添加成功就开启线程 同时修改状态
                    workerStarted = true ;
                }
            }
        } finally {
            if (! workerStarted )
                addWorkerFailed( w );
        }
        return workerStarted ;
    }
   
   //看run()方法
    private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
         final Thread thread ;
    
        Runnable firstTask ;
       
        volatile long completedTasks ;
      
       Worker(Runnable firstTask ) {
            setState(-1); // inhibit interrupts until runWorker
            this . firstTask = firstTask ;
            this . thread = getThreadFactory().newThread( this );
        }
     
        public void run() {
            runWorker( this );
        }
     
        protected boolean isHeldExclusively() {
            return getState() != 0;
        }
        protected boolean tryAcquire( int unused ) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true ;
            }
            return false ;
        }
        protected boolean tryRelease( int unused ) {
            setExclusiveOwnerThread( null );
            setState(0);
            return true ;
        }
        public void lock()        { acquire(1); }
        public boolean tryLock()  { return tryAcquire(1); }
        public void unlock()      { release(1); }
        public boolean isLocked() { return isHeldExclusively(); }
        void interruptIfStarted() {
            Thread t ;
            if (getState() >= 0 && ( t = thread ) != null && ! t .isInterrupted()) {
                try {
                    t .interrupt();
                } catch (SecurityException ignore ) {
                }
            }
        }
    }
  

  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 ) {  // ( task = getTask()) 从缓冲队列取数据
                w .lock();
              
                if ((runStateAtLeast( ctl .get(), STOP ) ||
                     (Thread.interrupted() &&
                     runStateAtLeast( ctl .get(), STOP ))) &&
                    ! wt .isInterrupted())                   //线程池的状态大于等于STOP时 中断该线程
                    wt .interrupt();
                try {
                    beforeExecute( wt , task );  //任务执行前调用,可由自己进行重写
                    Throwable thrown = null ;
                    try {
                        task .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 );
        }
    }
private RunnablegetTask() {
        boolean timedOut = false ; // Did the last poll() time out?
        for (;;) {
            int c = ctl .get();
            int rs =runStateOf( c );
      
            if ( rs >= SHUTDOWN && ( rs >= STOP || workQueue .isEmpty())) {  //当前线程池不允许执行任务时执行
                decrementWorkerCount();  
                return null ;
            }
            int wc =workerCountOf( c );
            // Are workers subject to culling?
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize ;  //超时时间是否生效,  
            if (( wc > maximumPoolSize || ( timed && timedOut ))
                && ( wc > 1 || workQueue .isEmpty())) {
                if (compareAndDecrementWorkerCount( c ))
                    return null ;
                continue ;
            }
            try {
                Runnable r = timed ?
                    workQueue .poll( keepAliveTime , TimeUnit. NANOSECONDS ) :  //在规定时间内取任务,否则就是超时
                    workQueue .take();   没有时间的限制,取任务
                if ( r != null )
                    return r ;
                timedOut = true ;
            } catch (InterruptedException retry ) {
                timedOut = false ;
            }
        }
    }
             }