学习整理——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():线程池只有一个工作线程,并能够按时间计划来执行任务。
- 学习整理——Java线程池
- java 线程学习 网址整理
- Java知识整理——线程
- Java,关于线程的学习的整理
- java线程学习(1)—线程安全
- java线程学习(八)—线程封闭
- java线程学习(六)—线程状态图
- java基础学习—线程
- java再学习—线程
- JAVA知识点整理第六部分——线程
- (48)Java学习笔记——多线程 / 线程间通信 / 线程组 / 线程池 /
- 学习整理——Java设计模式
- 学习整理——Java序列化
- 学习整理——Java集合Collection
- 学习整理——Java注解
- JAVA中线程池的整理
- Java线程编程整理
- JAVA线程知识整理
- HDU 2089
- 求一个正整数可以由几对素数构成
- 循环语句与方法的调用
- Fragment详解
- POJ 3080 Blue Jeans
- 学习整理——Java线程池
- 【基础算法】:树,森林,二叉树的转化
- js学习笔记:基本类型和引用类型
- HTTP协议请求头信息和响应头信息详解
- C++宏定义详解
- Struts2入门——2,先写一个小例子
- 迷宫问题的最短路径
- SQL通配符
- 不想丑陋之动态加载模块初级篇