JDK1.5之后,增加了一个Executor让我们能更好的使用多线程。
它位于java.util.concurrent包下
因为是JDK内置类库,我们不需要导入任何第三方jar包。
代码实例:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Demo { public static void main(String[] args) { ExecutorService executorService=Executors.newFixedThreadPool(10); //创建10个线程的线程池 System.out.println("创建线程池后,回收线程池"); executorService.shutdown(); } }
Executors类下面有一个静态方法:newFixedThreadPool();表示创建固定数量的线程池。
线程池:内部有多个线程可以调用,系统初始化的时候已经new好,即堆内存开辟的多个线程统一管理。
Executors帮我们管理:进行有效的队列阻塞和调度(底层算法),如果是开发不必深入了解,只需会用就可以了。
以上三行代码最好查阅JDK文档:
public static ExecutorService newFixedThreadPool(int nThreads)方法返回接口ExecutorService
其中有个方法shutdown
此方法可以手工回收,而不必等到GC来回收资源,可以使我们的程序能行更加良好。
对于初学者,代码
ExecutorService executorService=Executors.newFixedThreadPool(10);
是多态,这个必须先明确。
其次查文档最好看Oracle官方给出的英文文档。
使用从父类Executor继承而来的方法execute,
execute()方法接收Runnable类型的参数,于是代码:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Demo { public static void main(String[] args) { ExecutorService executorService=Executors.newFixedThreadPool(10); //创建10个线程的线程池 executorService.execute(new Runnable() { //匿名内部类 @Override public void run() { // TODO Auto-generated method stub } }); executorService.shutdown(); } }
对出初学者,以上用了匿名内部类,这个必须明确。
接口 ExecutorService有一个实现类ThreadPoolExecutor,
其中有一个方法public int getActiveCount()可以返回活动的线程数
public class Demo { private static Integer page=1; public static void main(String[] args) { ExecutorService executorService=Executors.newFixedThreadPool(10); //创建10个线程的线程池 while(true){ if(page<=100){ executorService.execute(new Runnable() { //匿名内部类 @Override public void run() { System.out.println("抓去了第"+page+"个网页"); page++; } }); }else{ //接口 ExecutorService有一个实现类ThreadPoolExecutor, //其中有一个方法public int getActiveCount() ThreadPoolExecutor threadPoolExecutor=(ThreadPoolExecutor)executorService; //向下转型(强制) if(threadPoolExecutor.getActiveCount()==0){ //活动线程数为零 executorService.shutdown(); System.out.println("任务结束"); break; //跳出循环 } } //因为太快,我们测试时休眠一下 try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
对于初学者必须明确,ThreadPoolExecutor类型向上转型到ExecutorService接口类型,需要强制转换,
之后我们运行,如下图: