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方法中加上信号量,这样就能够保证,线程池中线程能够重用,只有当你销毁线程池的时候,全部线程才会销毁。