线程池
作用:
不会频繁创建和销毁线程,有新线程(任务)到来时,先到线程池中寻找是否有空闲线程,如果有,就唤醒空闲线程执行任务。直接调用目标线程的run()方法,而不是使用start()方法。这样做可以减少创建线程并使线程处于就绪态占用的系统资源。
如果没有空闲线程,则新创建一个线程。
package threadPoolTest;
import java.util.Vector;
public class ThreadPool {
private static ThreadPool instance = null;
private Vector<PThread> idleThreads;
private boolean isShutDown = false;
/**
* 线程池中开启的线程数量
*/
private int threadCount;
/**
* 使用线程池中线程数量
*/
private int userPoolThreadCount;
private ThreadPool() {
this.idleThreads = new Vector<PThread>(5);
threadCount = 0;
userPoolThreadCount = 0;
}
public synchronized static ThreadPool getInstance() {
if (instance == null) {
instance = new ThreadPool();
}
return instance;
}
public int getThreadCount() {
return threadCount;
}
public void repool(PThread thread) {
if (!isShutDown) {
idleThreads.add(thread);
} else {
thread.shutDown();
}
}
public synchronized void start(Runnable target) {
PThread thread = null;
if (idleThreads.size() > 0) {
System.out.println("线程池中线程使用前的数量"+idleThreads.size());
int lastIndex = idleThreads.size() - 1;
thread = (PThread) idleThreads.get(lastIndex);
idleThreads.remove(lastIndex);
System.out.println("使用线程池中线程的次数"+userPoolThreadCount++);
System.out.println("使用线程池中的线程的名称"+thread.getName());
System.out.println("线程池中线程使用后的数量"+idleThreads.size());
// 立即执行任务
thread.setTarget(target);
} else {
threadCount++;
System.out.println("线程池中新开启的线程数量threadCount" + threadCount);
//当有任务线程来时,将其包装成PThread线程,不然线程执行一次就停止了,不能再次用于下一个线程的执行。
thread = new PThread(target, "PThread#" + threadCount, this);
thread.start();
}
}
public synchronized void shutDown() {
System.out.println("线程池中线程的数量:"+idleThreads.size());
isShutDown = true;
for (int threadIndex = 0; threadIndex < idleThreads.size(); threadIndex++) {
PThread thread = idleThreads.get(threadIndex);
thread.shutDown();
}
}
}
PThread
要使用上述线程池,需要放到线程池中的线程可以一直运行。这里使用PThread线程,它的主体是一个无限循环,该线程执行完后可以让其处于wait()状态,等待有新任务来时将其唤醒,再持续新线程(目标线程)的run()方法,这样就可以少创建线程。
当有任务线程来时,将其包装成PThread线程,不然线程执行一次就停止了,不能再次用于下一个线程的执行。
package threadPoolTest;
public class PThread extends Thread {
/**
* 線程池
*/
private ThreadPool pool;
/**
* 目標線程
*/
private Runnable target;
/**
* 线程是否关闭
*/
private boolean isShutDown = false;
/**
* 线程是否空闲
*/
private boolean isIdle = false;
public PThread(Runnable target, String name, ThreadPool pool) {
super(name);
this.target = target;
this.pool = pool;
}
public synchronized void setTarget(Runnable target) {
this.target = target;
notifyAll();
}
public void run(){
while(!isShutDown){
isIdle = false;
if(target !=null){
target.run();
}
isIdle = true;
try{
//不管是新创建的线程,还是在线程池中被使用后的线程,运行完后,应该再次放到线程池中。
pool.repool(this);
synchronized (this) {
wait();
}
} catch(Exception e){
}
isIdle = false;
}
}
public synchronized void shutDown(){
isShutDown = true;
notifyAll();
}
}
用户的任务线程MyThread
package threadPoolTest;
public class MyThread implements Runnable {
protected String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
try {
Thread.sleep(100);
System.out.println("myThread name"+name);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试代码TestMain
package threadPoolTest;
public class TestMain {
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 20; i++) {
Thread.sleep(10);
MyThread myThread = new MyThread("myThread" + i);
ThreadPool.getInstance().start(myThread);
}
// System.out.println("最后线程池中开启线程数量:"+ThreadPool.getInstance().getThreadCount());
//此处直接这样写是有问题的,因为上面的线程没有执行完的时候就会直接执行到这里来,导致线程池中的数量不正确。应该加上Threal.sleep(300000)。即等待上面的线程全部执行完,再执行关闭。
ThreadPool.getInstance().shutDown();
}
}
运行结果
线程池中新开启的线程数量threadCount1
线程池中新开启的线程数量threadCount2
线程池中新开启的线程数量threadCount3
线程池中新开启的线程数量threadCount4
线程池中新开启的线程数量threadCount5
线程池中新开启的线程数量threadCount6
线程池中新开启的线程数量threadCount7
线程池中新开启的线程数量threadCount8
myThread namemyThread0
线程池中线程使用前的数量1
使用线程池中线程的次数0
myThread namemyThread1
使用线程池中的线程的名称PThread#1
线程池中线程使用后的数量1
线程池中线程使用前的数量1
使用线程池中线程的次数1
使用线程池中的线程的名称PThread#2
线程池中线程使用后的数量0
myThread namemyThread2
线程池中线程使用前的数量1
使用线程池中线程的次数2
使用线程池中的线程的名称PThread#3
线程池中线程使用后的数量0
myThread namemyThread3
线程池中线程使用前的数量1
myThread namemyThread4
使用线程池中线程的次数3
使用线程池中的线程的名称PThread#4
线程池中线程使用后的数量1
线程池中线程使用前的数量1
使用线程池中线程的次数4
myThread namemyThread5
使用线程池中的线程的名称PThread#5
线程池中线程使用后的数量1
myThread namemyThread6
线程池中线程使用前的数量2
使用线程池中线程的次数5
使用线程池中的线程的名称PThread#7
线程池中线程使用后的数量1
线程池中线程使用前的数量1
使用线程池中线程的次数6
使用线程池中的线程的名称PThread#6
线程池中线程使用后的数量0
myThread namemyThread7
线程池中线程使用前的数量1
使用线程池中线程的次数7
myThread namemyThread8
使用线程池中的线程的名称PThread#8
线程池中线程使用后的数量1
线程池中线程使用前的数量1
使用线程池中线程的次数8
使用线程池中的线程的名称PThread#1
线程池中线程使用后的数量0
myThread namemyThread9
myThread namemyThread10
线程池中线程使用前的数量1
使用线程池中线程的次数9
使用线程池中的线程的名称PThread#3
线程池中线程使用后的数量1
线程池中线程使用前的数量1
使用线程池中线程的次数10
myThread namemyThread11
使用线程池中的线程的名称PThread#2
线程池中线程使用后的数量1
myThread namemyThread12
线程池中线程使用前的数量2
使用线程池中线程的次数11
使用线程池中的线程的名称PThread#5
线程池中线程使用后的数量1
线程池中线程的数量:1
myThread namemyThread13
myThread namemyThread14
myThread namemyThread15
myThread namemyThread16
myThread namemyThread17
myThread namemyThread18
myThread namemyThread19