Thread|Thread & ThreadPoolExecutor

Thread.State

  • NEW
Thread state for a thread which has not yet started.
这里就是我们平时New完一个线程后的初始状态。
  • RUNNABLE
Thread state for a runnable thread. A thread in the runnable state is executing in the Java virtual machine but it may be waiting for other resources from the operating system such as processor
调用了start()方法后线程进入运行状态。
  • BLOCKED
Thread state for a thread blocked waiting for a monitor lock. A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or reenter a synchronized block/method after calling
线程尝试获取锁(synchronized)失败后,进入等待阻塞状态。
  • WAITING
【Thread|Thread & ThreadPoolExecutor】Thread state for a waiting thread. Thread in the waiting state is waiting for another thread to perform a particular action.
线程获取锁后,调用wait()后,此时已经释放锁,需要获取锁的其他线程调用notify重新竞争锁。
  • TIMED_WAITING
Thread in the waiting state is waiting for another thread to perform a particular action.
调用wait(Time) 后等待一定时间,时间到后自动唤醒重新获得锁
  • TERMINATED
Thread state for a terminated thread. The thread has completed execution.
线程终止,已经执行完毕。
Thread中断
在线程运行(run)中间打断,Java中提供了3种方法:
//中断线程(实例方法) public void Thread.interrupt(); //判断线程是否被中断(实例方法) public boolean Thread.isInterrupted(); //判断是否被中断并清除当前中断状态(静态方法) public static boolean Thread.interrupted();

当一个线程处于被阻塞状态或者试图执行一个阻塞操作时,使用Thread.interrupt()方式中断该线程,此时将会抛出异常,同时中断状态将会被复位(由中断状态改为非中断状态),如我们创建一个线程,并在线程中调用了sleep方法从而使用线程进入阻塞状态,启动线程后,调用线程实例对象的interrupt方法后线程会进入阻塞异常,并抛出InterruptedException异常,此时中断状态也将被复位。
除了阻塞中断的情景,我们还可能会遇到处于运行期且非阻塞的状态的线程,这种情况下,Thread.interrupt()是不会得到任响应的,非阻塞状态下的线程需要我们手动进行中断检测并结束程序,例如:
...... while(true){ //判断当前线程是否被中断 if (this.isInterrupted()){ System.out.println("线程中断"); break; } } ......

综合所述,可以简单总结一下中断两种情况,一种是当线程处于阻塞状态或者试图执行一个阻塞操作时,我们可以使用实例方法interrupt()进行线程中断,执行中断操作后将会抛出interruptException异常(该异常必须捕捉无法向外抛出)并将中断状态复位,另外一种是当线程处于运行状态时,我们也可调用实例方法interrupt()进行线程中断,但同时必须手动判断中断状态,并编写中断线程的代码(其实就是结束run方法体的代码)。
中断与synchronized
线程的中断操作对于正在等待获取的锁对象的synchronized方法或者代码块并不起作用,也就是对于synchronized来说,如果一个线程在等待锁,那么结果只有两种,要么它获得这把锁继续执行,要么它就保存等待,即使调用中断线程的方法,也不会生效,不过此时isInterrupted()为true。
等待唤醒机制与synchronized
等待唤醒机制本篇主要指的是notify/notifyAll和wait方法,在使用这3个方法时,必须处于synchronized代码块或者synchronized方法中,否则就会抛出IllegalMonitorStateException异常,这是因为调用这几个方法前必须拿到当前对象的监视器monitor对象,也就是说notify/notifyAll和wait方法依赖于monitor对象(synchronized关键字可以获取monitor)
需要特别理解的一点是,与sleep方法不同的是wait方法调用完成后,线程将被暂停,但wait方法将会释放当前持有的监视器锁(monitor),直到有线程调用notify/notifyAll方法后方能继续执行,而sleep方法只让线程休眠并不释放锁。同时notify/notifyAll方法调用后,并不会马上释放监视器锁,而是在相应的synchronized(){}/synchronized方法执行结束后才自动释放锁。
ThreadPoolExecutor
Thread|Thread & ThreadPoolExecutor
文章图片
diagrams.png
  • corePoolSize : 线程池中的线程数量,包括空闲线程
Core pool size is the minimum number of workers to keep alive (and not allow to time out etc) unless allowCoreThreadTimeOut is set, in which case the minimum is zero.
  • maxmumPoolSize : 池中允许的最大线程数
Maximum pool size. Note that the actual maximum is internally bounded by CAPACITY.
  • keepAliveTime : 线程数大于核心数时,空闲线程等待任务的有效时间,用于空闲线程过多时回收线程的参数
Timeout in nanoseconds for idle threads waiting for work. Threads use this timeout when there are more than corePoolSize present or if allowCoreThreadTimeOut. Otherwise they wait forever for new work.
  • workQueue:存储任务的队列,当前线程数量在coreSize和maxSize之间时,会先将任务放入队列中等待执行,若队列已满,会创建线程(不超过最大线程数)
The queue used for holding tasks and handing off to worker threads. We do not require that workQueue.poll() returning null necessarily means that workQueue.isEmpty(), so rely solely on isEmpty to see if the queue is empty (which we must do for example when deciding whether to transition from SHUTDOWN to TIDYING). This accommodates special-purpose queues such as DelayQueues for which poll() is allowed to return null even if it may later return non-null when delays expire.
  • threadFactory:创建线程的工厂类
Factory for new threads. All threads are created using this factory (via method addWorker).
  • handler:线程池和等待队列已满时执行的拒绝策略
Handler called when saturated or shutdown in execute.
  • 线程池的运行思路
When a new task is submitted in method {@link #execute(Runnable)}, and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle. If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full. By setting corePoolSize and maximumPoolSize the same, you create a fixed-size thread pool. By setting maximumPoolSize to an essentially unbounded value such as {@code Integer.MAX_VALUE}, you allow the pool to accommodate an arbitrary number of concurrent tasks. Most typically, core and maximum pool sizes are set only upon construction, but they may also be changed dynamically using {@link #setCorePoolSize} and {@link #setMaximumPoolSize}.
当前线程数量小于corePoolSize时,会直接新建线程执行新提交的Runnable。
当前线程数量大于corePoolSize且等待队列未满,新提交的Runnable会加入等待队列中。
当前线程数量大于corePoolSize小于maximumPoolSize,且等待队列已满,会直接新建线程执行新提交的Runnable。
New tasks submitted in method {@link #execute(Runnable)} will be em>rejected when the Executor has been shut down, and also when the Executor uses finite bounds for both maximum threads and work queue capacity, and is saturated.
当前线程数量大于maximumPoolSize,且等待队列已满,会采取拒绝策略。
In the default {@link ThreadPoolExecutor.AbortPolicy}, the handler throws a runtime {@link RejectedExecutionException} upon rejection.
默认策略AbortPolicy,会抛出一个运行时异常。
In {@link ThreadPoolExecutor.CallerRunsPolicy}, the thread that invokes {@code execute} itself runs the task. This provides a simple feedback control mechanism that will slow down the rate that new tasks are submitted.
CallerRunsPolicy策略,调用线程自己直接run task。
In {@link ThreadPoolExecutor.DiscardPolicy}, a task that cannot be executed is simply dropped.
DiscardPolicy策略,直接抛弃Runnable不会有异常。
In {@link ThreadPoolExecutor.DiscardOldestPolicy}, if the executor is not shut down, the task at the head of the work queue is dropped, and then execution is retried (which can fail again, causing this to be repeated.)
DiscardOldestPolicy策略,丢弃队列中头部的任务,再次尝试提交任务,如果再次失败则重复此策略。
If the pool currently has more than corePoolSize threads,excess threads will be terminated if they have been idle for more than the keepAliveTime
如果线程池的当前数量大于corePoolSize,额外的线程闲置时间超过 keepAliveTime 会自动停止。
In {@link ThreadPoolExecutor.CallerRunsPolicy}, the thread that invokes {@code execute} itself runs the task. This provides a simple feedback control mechanism that will slow down the rate that new tasks are submitted.

    推荐阅读