您的位置:首页 > 编程语言 > Java开发

java自定义线程池

2018-01-26 17:10 309 查看

线程池

作用:

不会频繁创建和销毁线程,有新线程(任务)到来时,先到线程池中寻找是否有空闲线程,如果有,就唤醒空闲线程执行任务。直接调用目标线程的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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: