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
相关文章推荐
- Java自定义线程池-ThreadPoolExecutor
- Java并发编程---自定义线程池
- java自定义线程池
- java ThreadPoolExecutor 自定义线程池demo
- java 自带线程池与自定义线程池
- java线程安全之Executor框架及自定义线程池(十五)
- 【Java多线程】写入同一文件,自定义线程池与线程回收利用
- 自定义java 线程池
- Java 自定义 线程池与任务队列
- java多线程学习笔记之自定义线程池
- Java 自定义 线程池与任务队列
- 自定义Java线程池 ThreadPoolExecutor
- Java自定义拒绝策略与线程池
- java 自定义线程池
- Java自定义线程池和线程总数控制
- java多线程(四)-自定义线程池
- Java自定义线程池详解
- 【Java多线程】写入同一文件,自定义线程池与线程回收利用2
- 【Java多线程】写入同一文件,自定义线程池与线程回收利用
- java.util.concurrent解读,自定义线程工厂,线程池