JAVA学习记录 – 线程Ⅰ
将一些基础知识整理出来,方便后面查看
1. Thread
1.1 API说明:
A thread is a thread of execution in a program. The Java Virtual Machine allows an application to have multiple threads of execution running concurrently.
Every thread has a priority. Threads with higher priority are executed in preference to threads with lower priority. Each thread may or may not also be marked as a daemon. When code running in some thread creates a new Thread object, the new thread has its priority initially set equal to the priority of the creating thread, and is a daemon thread if and only if the creating thread is a daemon.
When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class). The Java Virtual Machine continues to execute threads until either of the following occurs:
The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.
There are two ways to create a new thread of execution. One is to declare a class to be a subclass of Thread. This subclass should override the run method of class Thread. An instance of the subclass can then be allocated and started.
- 从API的说明中可以看出,只有当线程是守护线程时,其生成的线程也是守护线程1。
- 被创建的线程是有优先级的,优先级与创建线程保持一致,线程的执行顺序是和优先级相关的。
1.2 线程的创建:
有两种方式创建新的线程:
One is to declare a class to be a subclass of Thread
. This subclass should override the run
method of class Thread
. An instance of the subclass can then be allocated and started. For example, a thread that computes primes larger than a stated value could be written as follows:
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
The following code would then create a thread and start it running:
PrimeThread p = new PrimeThread(143);
p.start();
第一种方式是继承Thread类来实现新的线程的创建。
The other way to create a thread is to declare a class that implements the Runnable
interface. That class then implements the run
method. An instance of the class can then be allocated, passed as an argument when creating Thread
, and started. The same example in this other style looks like the following:
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
The following code would then create a thread and start it running:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
第二种方式是通过继承Runable来实现新的线程的创建。
2.ThreadFactory
2.1 API说明:
An object that creates new threads on demand. Using thread factories removes hardwiring of calls to new Thread, enabling applications to use special thread subclasses, priorities, etc.
线程工厂类是根据指定的方式自动生成新的线程,用以代替手动创建的方式。
2.2 JDK示例如下:
static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
ThreadFactory可以在ThreadPoolExecutor中使用,线程池直接使用线程工厂来创建新的线程,无需使用手动进行创建
3 ThreadPoolExecutor2
3.1 API说明
An {@link ExecutorService} that executes each submitted task using one of possibly several pooled threads, normally configured using {@link Executors} factory methods.
Thread pools address two different problems: they usually provide improved performance when executing large numbers of asynchronous tasks, due to reduced per-task invocation overhead,and they provide a means of bounding and managing the resources,including threads, consumed when executing a collection of tasks.Each {@code ThreadPoolExecutor} also maintains some basic statistics, such as the number of completed tasks.
3.2 接口举例分析
3.2.1 接口API
Creates a new {@code ThreadPoolExecutor} with the given initial parameters.
@param corePoolSize the number of threads to keep in the pool, even if they are idle, unless {@code allowCoreThreadTimeOut} is set
@param maximumPoolSize the maximum number of threads to allow in the pool
@param keepAliveTime when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.
@param unit the time unit for the {@code keepAliveTime} argument
@param workQueue the queue to use for holding tasks before they are executed. This queue will hold only the {@code Runnable} tasks submitted by the {@code execute} method.
@param threadFactory the factory to use when the executor creates a new thread
@param handler the handler to use when execution is blocked because the thread bounds and queue capacities are reached
@throws IllegalArgumentException if one of the following holds:
{@code corePoolSize < 0}
{@code keepAliveTime < 0}
{@code maximumPoolSize <= 0}
{@code maximumPoolSize < corePoolSize}@throws NullPointerException if {@code workQueue} or {@code threadFactory} or {@code handler} is null
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
3.2.2 参数分析
- corePoolSize 核心线程数量
线程一直保持的数量,线程池中永久保存执行的线程数量。 - maximumPoolSize 最大线程数量
线程池中的线程最多不能超过此参数设置的数量。当线程数量大于corePoolSize时,会启动新的线程来满足线程的执行。 - keepAliveTime 线程存活时间
任务队列中空闲线程3的存活时间,当阈值时间内无法获取到新的任务,则销毁此线程。 - unit keepAliveTime的时间单位
- workQueue 执行队列
执行队列是对任务的缓存,当任务还没有分配线程执行时,放入到此队列中4。 - threadFactory 线程工厂
- handler 处理程序
当线程数达到阈值并且workQueue已经满的情况下,处理程序对任务按照指定处理方式进行处理。
3.2.3 接口使用
调用接口时返回ThreadPoolExecutor,然后使用ThreadPoolExecutor.execute。如下例:
ThreadPoolExecutor a = new ThreadPoolExecutor(5,5,5, TimeUnit.DAYS, queen);
a.execute(r);
3.2.4 RejectedExecutionHandler
- ThreadPoolExecutor.AbortPolicy
A handler for rejected tasks that throws a {@code RejectedExecutionException}.用于处理被拒绝的处理程序,将抛出RejectedExecutionException。 - ThreadPoolExecutor.CallerRunsPolicy
A handler for rejected tasks that runs the rejected task directly in the calling thread of the {@code execute} method,unless the executor has been shut down, in which case the task is discarded.用于被拒绝任务的处理程序,直接在execute方法的调用线程中运行被拒绝的任务;如果执行程序已经关闭,则会丢弃该任务。 - ThreadPoolExecutor.DiscardOldestPolicy
A handler for rejected tasks that discards the oldest unhandled request and then retries {@code execute}, unless the executor is shut down, in which case the task is discarded.用于被拒绝任务的处理程序,将放弃存在时间最久的未处理请求,然后重试execute;如果执行程序已经关闭,则会丢弃该任务。 - ThreadPoolExecutor.DiscardPolicy
A handler for rejected tasks that silently discards the rejected task.用于被拒绝任务的处理从程序,默认情况下它将丢弃被拒绝的任务。