1.三、提升線程的可管理性。線程是稀缺資源,若是無限制的建立,不只會消耗系統資源,還會下降系統的穩定性,使用線程池能夠進行統一的分配,調優和監控。可是要作到合理的利用線程池,必須對其原理了如指掌。ide
import java.util.LinkedList;
import java.util.List;
public class NewThreadPool {
volatile int counter =0;
private static int WORKNUM = 5;
List<Runnable> taskQueue = new LinkedList<Runnable>();
// 已處理的任務
private static volatile int finished_task = 0;
private WorkThread[] workThreads;
private static NewThreadPool newThreadPool;
private NewThreadPool(int workNum) {
NewThreadPool.WORKNUM = workNum;
// 定義一個工做線程數組
workThreads = new WorkThread[workNum];
for (int i = 0; i < workThreads.length; i++) {
workThreads[i] = new WorkThread();
workThreads[i].start();
}
}
// 單例模式得到默認線程個數的線程池
public static NewThreadPool getThreadPool() {
return getNewThreadPool(NewThreadPool.WORKNUM);
}
// 得到傳入參數個數的線程池,大小不能小於默認個數
public static NewThreadPool getNewThreadPool(int work_num) {
if (work_num <= 0) {
work_num = NewThreadPool.WORKNUM;
}
if (null == newThreadPool) {
newThreadPool = new NewThreadPool(work_num);
}
return newThreadPool;
}
//執行線程
public void execute(Runnable task){
synchronized (taskQueue) {
taskQueue.add(task);
taskQueue.notify();
}
}
//批量執行線程任務
public void execute(Runnable[] task){
synchronized (taskQueue) {
for(Runnable t : task ){
taskQueue.add(t);
taskQueue.notify();
}
}
}
public void execute(List<Runnable>task){
synchronized (taskQueue) {
for(Runnable t : task){
taskQueue.add(t);
taskQueue.notify();
}
}
}
//返回工做線程的個數
public int getWorkedThreadNumbers(){
return WORKNUM;
}
//返回已經完成的線程任務
public int getFinishedTaskNumbers(){
return finished_task;
}
//返回尚未完成任務的的線程個數
public int getWaitTaskNumbers(){
return taskQueue.size();
}
//銷燬線程池方法,等到全部線程都完成以後纔會銷燬
public void destory(){
while(!taskQueue.isEmpty()){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int i=0;i<WORKNUM;i++){
workThreads[i].stopWorker();
workThreads[i] = null;
}
newThreadPool = null;
taskQueue.clear();
}
// 覆蓋toString方法,返回線程池信息:工做線程個數和已完成任務個數
@Override
public String toString() {
return "WorkThread number:" + WORKNUM + " finished task number:"
+ finished_task + " wait task number:" + getWaitTaskNumbers();
}
// 工做線程
private class WorkThread extends Thread {
private boolean isRunning = true;
@Override
public void run() {
Runnable r = null;
while (isRunning) {
synchronized (taskQueue) {
while (isRunning && taskQueue.isEmpty()) {
try {
taskQueue.wait(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 因爲是隊列,取第0個
if (!taskQueue.isEmpty()) {
r = taskQueue.remove(0);
}
}
if (null != r) {
r.run();
//stopWorker();
}
System.out.println(Thread.currentThread().getName() + "------------" + counter++ +"-----" + getWaitTaskNumbers());
finished_task++;
r = null;
}
}
// 中止工做,讓該線程天然執行完run方法,天然結束
public void stopWorker() {
isRunning = false;
}
}
}
//測試線程池
public class TestThreadPool {
public static void main(String[] args) {
// 建立3個線程的線程池
NewThreadPool t = NewThreadPool.getNewThreadPool(10);
t.execute(new Runnable[] { new Task(), new Task(), new Task() , new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task()});
t.execute(new Runnable[] { new Task(), new Task(), new Task() , new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task()});
System.out.println(t);
//t.destory();// 全部線程都執行完成才destory
System.out.println(t);
t.execute(new Runnable[] { new Task(), new Task(), new Task() , new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task(), new Task()});
}
// 任務類
static class Task implements Runnable {
private static volatile int i = 1;
@Override
public void run() {// 執行任務
System.out.println("任務 " + (i++) + " 完成");
}
}
}
在編寫線程池的時候,咱們須要有一個基本的思路。須要一個基本的思路,一個安全的線程隊列用來存放線程。按照要求初始化默認數量的線程,而且啓動它,讓這些線程在等待隊列中等待,而後當目標任務來時,將其喚醒得到鎖而後處理目標任務。
因爲隊列是不安全的,因此在線程添加到隊列,和從隊列中取出來的時候,都須要同步synchroniza,保證其安全。還有一個概念就是一旦線程池中run方法跑完,那麼它的生命週期也就結束了。線程狀態轉換,參考 線程基礎(詳細介紹線程狀態轉換) ,因此再咱們須要一個信號量,將工做線程的run方法中加上信號量,這樣就能夠保證,線程池中線程能夠重用,只有當你銷燬線程池的時候,全部線程纔會銷燬。