線程
<code>java<code> 創(chuàng)建線程最簡(jiǎn)單的方式就是繼承<code>Thread</code>類或者實(shí)現(xiàn) <code>Runnable</code>接口實(shí)現(xiàn) <code>run()</code> 方法陈症,然后調(diào)用 <code>start()</code> 方法來讓線程執(zhí)行漂问。
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] 這個(gè)是輸出的是線程名赖瞒,線程優(yōu)先級(jí)以及線程組的名字,具體可以看<code>Thread</code> 的<code>toString()</code> 方法
實(shí)際上 實(shí)現(xiàn) Runnable 接口的類可以看做是一個(gè)任務(wù)(<code>task</code>)真正創(chuàng)建線程的是 <code>Thread</code>類
線程池
JDK 中提供了 Executor 框架來創(chuàng)建線程池蚤假。
其中 <code>Executors</code>作為工廠類 提供了幾個(gè)創(chuàng)建線程的工廠方法
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> 接收一個(gè) <code>int</code> 參數(shù)栏饮,返回一個(gè)固定大小的線程池,上面代碼的輸出可以看出十個(gè)任務(wù)提交到線程池中,前5個(gè)和后面的5個(gè)執(zhí)行相差了1秒磷仰。
如果換成<code>newCachedThreadPool()</code>來創(chuàng)建線程池則會(huì)得到如下輸出:
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>來實(shí)現(xiàn)
<code>ThreadPoolExecutor</code>中提供了四個(gè)構(gòu)造方法袍嬉,而其他三個(gè)都是通過下圖這個(gè)構(gòu)造方法來實(shí)現(xiàn)。
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> 指定線程池中保持的線程數(shù)量灶平,即使他們是空閑的伺通,除非設(shè)置了<code>allowCoreThreadTimeOut</code>
<code> maximumPoolSize </code> 指定線程池允許創(chuàng)建的最大線程數(shù)量
<code> keepAliveTime </code> 當(dāng)線程池中的線程數(shù)量大于<code> corePoolSize </code>設(shè)置的數(shù)量時(shí),大于<code> corePoolSize </code>數(shù)量的那部分線程等待新任務(wù)的最大等待時(shí)間逢享,當(dāng)超過這個(gè)時(shí)間多出來的線程將會(huì)被銷毀罐监。
<code> unit </code> <code> keepAliveTime </code>的時(shí)間單位
<code> workQueue </code> 用于保存通過 <code>execute</code> 方法提交并且未來得及執(zhí)行的任務(wù)。
<code> threadFactory </code> 用來創(chuàng)建線程的線程工廠
<code> handler </code> 當(dāng)線程池中線程數(shù)量到達(dá)極限并且 workQueue達(dá)到最大容量時(shí) 處理任務(wù)的拒絕策略
workQueue傳入的是一個(gè) <code>BlockingQueue</code>類型的參數(shù)瞒爬,用于保存 Runnable 對(duì)象
可使用的<code>BlockingQueue</code>有:
<code>SynchronousQueue</code> 直接提交的隊(duì)列
<code>ArrayBlockingQueue</code> 有界隊(duì)列
<code>LinkedBlockingQueue</code> 無界隊(duì)列
<code>PriorityBlockingQueue</code> 優(yōu)先級(jí)隊(duì)列
<code>handler</code>
有四種拒絕策略
<code>AbortPolicy</code> 直接拋出異常
<code>DiscardPolicy</code> 默默拋棄
<code>DiscardOldestPolicy</code> 丟棄最老的任務(wù)弓柱,也就是即將執(zhí)行的任務(wù)
<code>CallerRunsPolicy</code> 在調(diào)用線程中執(zhí)行