java自定义线程池

线程池

作用:
不会频繁创建和销毁线程,有新线程(任务)到来时,先到线程池中寻找是否有空闲线程,如果有,就唤醒空闲线程执行任务。直接调用目标线程的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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值