线程
<code>java<code> 创建线程最简单的方式就是继承<code>Thread</code>类或者实现 <code>Runnable</code>接口实现 <code>run()</code> 方法,然后调用 <code>start()</code> 方法来让线程执行。
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread());
}
}).start();
}
输出:
Thread[Thread-0,5,main] 这个是输出的是线程名,线程优先级以及线程组的名字,具体可以看<code>Thread</code> 的<code>toString()</code> 方法
实际上 实现 Runnable 接口的类可以看做是一个任务(<code>task</code>)真正创建线程的是 <code>Thread</code>类
线程池
JDK 中提供了 Executor 框架来创建线程池。
其中 <code>Executors</code>作为工厂类 提供了几个创建线程的工厂方法
public class ThreadTest {
public static void main(String[] args) {
TestTask tt = new TestTask();
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i <10;i++){
executorService.submit(tt);
}
}
}
class TestTask implements Runnable {
@Override
public void run() {
System.out.println(System.currentTimeMillis() + " Thread ID:" + Thread.currentThread().getId());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出:
1495507701904 Thread ID:10
1495507701905 Thread ID:11
1495507701904 Thread ID:9
1495507701905 Thread ID:12
1495507701905 Thread ID:13
1495507702909 Thread ID:9
1495507702909 Thread ID:12
1495507702909 Thread ID:11
1495507702909 Thread ID:13
1495507702909 Thread ID:10
<code>newFixedThreadPool(int nThreads)</code> 接收一个 <code>int</code> 参数,返回一个固定大小的线程池,上面代码的输出可以看出十个任务提交到线程池中,前5个和后面的5个执行相差了1秒。
如果换成<code>newCachedThreadPool()</code>来创建线程池则会得到如下输出:
1495508104585 Thread ID:9
1495508104586 Thread ID:10
1495508104586 Thread ID:11
1495508104586 Thread ID:12
1495508104586 Thread ID:13
1495508104586 Thread ID:14
1495508104587 Thread ID:15
1495508104587 Thread ID:16
1495508104587 Thread ID:17
1495508104587 Thread ID:18
线程池的核心
<code>Executors</code> 提供这些工厂方法都是通过<code>ThreadPoolExecutor</code>来实现
<code>ThreadPoolExecutor</code>中提供了四个构造方法,而其他三个都是通过下图这个构造方法来实现。
jdk 源码上提供的注释说明
/**
* 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:<br>
* {@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br>
* {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* @throws NullPointerException if {@code workQueue}
* or {@code threadFactory} or {@code handler} is null
*/
<code> corePoolSize </code> 指定线程池中保持的线程数量,即使他们是空闲的,除非设置了<code>allowCoreThreadTimeOut</code>
<code> maximumPoolSize </code> 指定线程池允许创建的最大线程数量
<code> keepAliveTime </code> 当线程池中的线程数量大于<code> corePoolSize </code>设置的数量时,大于<code> corePoolSize </code>数量的那部分线程等待新任务的最大等待时间,当超过这个时间多出来的线程将会被销毁。
<code> unit </code> <code> keepAliveTime </code>的时间单位
<code> workQueue </code> 用于保存通过 <code>execute</code> 方法提交并且未来得及执行的任务。
<code> threadFactory </code> 用来创建线程的线程工厂
<code> handler </code> 当线程池中线程数量到达极限并且 workQueue达到最大容量时 处理任务的拒绝策略
workQueue传入的是一个 <code>BlockingQueue</code>类型的参数,用于保存 Runnable 对象
可使用的<code>BlockingQueue</code>有:
<code>SynchronousQueue</code> 直接提交的队列
<code>ArrayBlockingQueue</code> 有界队列
<code>LinkedBlockingQueue</code> 无界队列
<code>PriorityBlockingQueue</code> 优先级队列
<code>handler</code>
有四种拒绝策略
<code>AbortPolicy</code> 直接抛出异常
<code>DiscardPolicy</code> 默默抛弃
<code>DiscardOldestPolicy</code> 丢弃最老的任务,也就是即将执行的任务
<code>CallerRunsPolicy</code> 在调用线程中执行