学习整理——Java线程池

来源:互联网 发布:网络thug life什么意思 编辑:程序博客网 时间:2024/06/05 20:07

线程VS线程池

为什么要使用线程池?我们知道,在Java创建并运行一个线程很简单,只需要实现run()方法并在合适时间点上调用start()方法即可。但是无法在表面看到的是,Java的Thread类调用native方法创建并运行一个线程需要多大的开销。如果在程序中需要有大量的线程执行,对于每一个线程都调用native去创建并运行,势必会造成很大的资源消耗,更多的计算资源集中在创建、开始、销毁线程的工作上,而这时线程池的出现可以解决这方面的问题。所谓线程池就是事先在一个池里创建多个线程并执行它们,即使是空任务它们也可以在循环里跑。一旦外部有线程的执行需求,可以将该需求丢进池里,让其中的正在执行的线程去调用执行,而不是为该需求重新创建线程,节省系统开销。


使用线程池需要注意

1.线程池的大小:该大小决定着同一时间可以执行的任务数。如果太小的话,工作线程可能无法适应任务需求的速度,造成后进的线程需要等待较长时间;太大的话,会浪费内存和计算资源,因为工作线程在无任务的情况下依然会占用CPU时间,接受调度;

2.关闭线程池:使用完线程池需要执行关闭,不然执行完所有任务之后依然会占用CPU时间和内存;


代码

基于以上的初等认识,可以实现自己的线程池,当然需要改进和补充的地方还有很多。

线程池的更多介绍可以参考:传送门1  传送门2

import java.util.LinkedList;import java.util.List;public class MyThreadPool {private int poolSize;             // 核心池大小private MyConcreteThread[] concreteThread;             //  工作线程private List<Runnable> threadList = new LinkedList<Runnable>();   // 任务队列private static MyThreadPool threadPool = null;   //  单例模式private MyThreadPool(){this(5);                      //  默认大小}private MyThreadPool(int poolSize){this.poolSize = poolSize;concreteThread = new MyConcreteThread[poolSize];for(MyConcreteThread oneThread:concreteThread){oneThread = new MyConcreteThread();oneThread.start();                // 启动线程}}public static MyThreadPool getInstance(){if(threadPool == null){synchronized (MyThreadPool.class) {if(threadPool == null)threadPool = new MyThreadPool();}}return threadPool;}public static MyThreadPool getInstance(int poolSize){if(threadPool == null){synchronized (threadPool) {if(threadPool == null)threadPool = new MyThreadPool(poolSize);}}return threadPool;}//  添加单个线程public void execute(Runnable r){synchronized (threadList) {threadList.add(r);threadList.notify();}}//  批量添加线程public void execute(Runnable[] rs){synchronized (threadList) {for(Runnable r:rs)threadList.add(r);threadList.notify();}}//  获取线程池大小public int getPoolSize(){return poolSize;}// 工作线程,内部类class MyConcreteThread extends Thread{@Overridepublic void run(){while(!isInterrupted()){Runnable r = null;synchronized (threadList) {while(threadList.isEmpty()){try{threadList.wait();        //  该线程没有工作,让出队列对象}catch(InterruptedException e){e.printStackTrace();}}if(!threadList.isEmpty())r = threadList.remove(0);    //取出第一个}if(r != null){r.run();               // 在工作线程里调用run方法,相当于执行了该线程}r = null;}}}}

运行测试

单个添加

public class TestThreadPool {public static void main(String arg[]){Runnable r1 = new Runnable() {public void run() {System.out.println("Thread 1 run!");}};Runnable r2 = new Runnable() {public void run() {System.out.println("Thread 2 run!");}};MyThreadPool myThreadPool = MyThreadPool.getInstance();myThreadPool.execute(r1);myThreadPool.execute(r2);try{Thread.sleep(1000);}catch (Exception e) {e.printStackTrace();}System.out.println("Main thread end!");}}
结果

Thread 2 run!Thread 1 run!Main thread end!

Thread 1 run!Thread 2 run!Main thread end!


批量添加

public class TestThreadPool {public static void main(String arg[]){MyThreadPool myThreadPool = MyThreadPool.getInstance();TestThread[] tests = new TestThread[10];for(int i=0;i<10;i++){tests[i] = new TestThread(i);}myThreadPool.execute(tests);try{Thread.sleep(1000);}catch (Exception e) {e.printStackTrace();}System.out.println("Main thread end!");}}class TestThread extends Thread{private int number;public TestThread(int number){this.number = number;}@Overridepublic void run(){System.out.println("Thread "+ number + " run!");}}
运行

Thread 0 run!Thread 1 run!Thread 2 run!Thread 3 run!Thread 4 run!Thread 5 run!Thread 6 run!Thread 7 run!Thread 8 run!Thread 9 run!Main thread end!


jdk线程池

jdk已经为我们封装好了线程池,应用时可以放心使用,以下简单叙述下关于线程池的类。

Executor接口

线程池类都实现了该接口,该接口提供一个方法execute(),该方法接受一个Runnable类型的参数,表面上是执行该任务,实际上是将其提交到线程池中。


ExecutorService接口

继承Executor,在Executor的基础上多提供了几个接口。


ThreadPoolExecutor类

用户自定义配置的线程池类,实例出来即可以用。


Executor类

实现了ExecutorService。对于用户而言,有时候并不需要自己去配置线程池,该类则事先为我们创建好一个优秀的线程池,现在只需要去获取即可。

该类提供了几种配置的线程池,分别使用以下方法返回:

newCacheThreadPool():在有任务时才创建新线程,空闲线程被保留60秒;

newFixedThreadPool(int nThreads):线程池中包含固定数目的线程,空闲线程被一直保留。参数是设置线程的数目;

newSingleThreadExecutor():线程池中只有一个工作线程,该线程会依次执行任务;

newScheduledThreadPool(int corePoolSize):线程池能按时间计划执行任务,允许用户设定计划执行任务的时间。参数corePoolSize设定工作线程的最小数目,如果任务较多,线程池可以动态增加工作线程;

newSingleThreadScheduledExecutor():线程池只有一个工作线程,并能够按时间计划来执行任务。



0 0
原创粉丝点击