线程池相关知识点
线程池的作用:
线程池作用就是限制系统中执行线程的数量。
根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。
为什么要用线程池:
1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下
要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此在Executors类里面提供了一些静态工厂,生成一些常用的线程池。
1. newSingleThreadExecutor
创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
2.newFixedThreadPool
创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
3. newCachedThreadPool
创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,
那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
4.newScheduledThreadPool
创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。
实例:
1:newSingleThreadExecutor
package com.thread; /* * 通过实现Runnable接口,实现多线程 * Runnable类是有run()方法的; * 但是没有start方法 * 参考: http://blog.csdn.net/qq_31753145/article/details/50899119 * */ public class MyThread extends Thread { @Override public void run() { // TODO Auto-generated method stub // super.run(); System.out.println(Thread.currentThread().getName()+"正在执行...."); } }
package com.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /* * 通过实现Runnable接口,实现多线程 * Runnable类是有run()方法的; * 但是没有start方法 * 参考: * http://blog.csdn.net/qq_31753145/article/details/50899119 * */ public class singleThreadExecutorTest{ public static void main(String[] args) { // TODO Auto-generated method stub //创建一个可重用固定线程数的线程池 ExecutorService pool=Executors.newSingleThreadExecutor(); //创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口; Thread t1=new MyThread(); Thread t2=new MyThread(); Thread t3=new MyThread(); Thread t4=new MyThread(); Thread t5=new MyThread(); //将线程放到池中执行; pool.execute(t1); pool.execute(t2); pool.execute(t3); pool.execute(t4); pool.execute(t5); //关闭线程池 pool.shutdown(); } }
2newFixedThreadPool
package com.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /* * 通过实现Runnable接口,实现多线程 * Runnable类是有run()方法的; * 但是没有start方法 * 参考: * http://blog.csdn.net/qq_31753145/article/details/50899119 * */ public class fixedThreadExecutorTest{ public static void main(String[] args) { // TODO Auto-generated method stub //创建一个可重用固定线程数的线程池 ExecutorService pool=Executors.newFixedThreadPool(2); //创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口; Thread t1=new MyThread(); Thread t2=new MyThread(); Thread t3=new MyThread(); Thread t4=new MyThread(); Thread t5=new MyThread(); //将线程放到池中执行; pool.execute(t1); pool.execute(t2); pool.execute(t3); pool.execute(t4); pool.execute(t5); //关闭线程池 pool.shutdown(); } }
结果:
pool-1-thread-1正在执行.... pool-1-thread-1正在执行.... pool-1-thread-1正在执行.... pool-1-thread-1正在执行.... pool-1-thread-2正在执行....
3、newCachedThreadPool
package com.thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /* * 通过实现Runnable接口,实现多线程 * Runnable类是有run()方法的; * 但是没有start方法 * 参考: * http://blog.csdn.net/qq_31753145/article/details/50899119 * */ public class cachedThreadExecutorTest{ public static void main(String[] args) { // TODO Auto-generated method stub //创建一个可重用固定线程数的线程池 ExecutorService pool=Executors.newCachedThreadPool(); //创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口; Thread t1=new MyThread(); Thread t2=new MyThread(); Thread t3=new MyThread(); Thread t4=new MyThread(); Thread t5=new MyThread(); //将线程放到池中执行; pool.execute(t1); pool.execute(t2); pool.execute(t3); pool.execute(t4); pool.execute(t5); //关闭线程池 pool.shutdown(); } }
结果:
pool-1-thread-2正在执行.... pool-1-thread-1正在执行.... pool-1-thread-3正在执行.... pool-1-thread-4正在执行.... pool-1-thread-5正在执行....
4、newScheduledThreadPool
package com.thread; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; /* * 通过实现Runnable接口,实现多线程 * Runnable类是有run()方法的; * 但是没有start方法 * 参考: * http://blog.csdn.net/qq_31753145/article/details/50899119 * */ public class scheduledThreadExecutorTest{ public static void main(String[] args) { // TODO Auto-generated method stub ScheduledThreadPoolExecutor exec =new ScheduledThreadPoolExecutor(1); exec.scheduleAtFixedRate(new Runnable(){//每隔一段时间就触发异常 @Override public void run() { // TODO Auto-generated method stub //throw new RuntimeException(); System.out.println("==================="); }}, 1000, 5000, TimeUnit.MILLISECONDS); exec.scheduleAtFixedRate(new Runnable(){//每隔一段时间打印系统时间,证明两者是互不影响的 @Override public void run() { // TODO Auto-generated method stub System.out.println(System.nanoTime()); }}, 1000, 2000, TimeUnit.MILLISECONDS); } }
结果:
=================== 23119318857491 23121319071841 23123319007891 =================== 23125318176937 23127318190359 =================== 23129318176148 23131318344312 23133318465896 =================== 23135319645812