为何须要执行框架呢?
使用通常的new方法来建立线程有什么问题呢?通常的new线程的方式通常要给出一个实现了Runnable接口的执行类,在其中重写run()方法,而后再在将这个执行类的对象传给线程以完成初始化,这个过程当中线程的定义和执行过程实际上是杂糅在一块儿了,并且每次new一个新的线程出来在资源上颇有可能会产生没必要要的消耗,所以咱们经过多线程执行框架来解决这两个问题,其一能够分离线程的定义和执行过程,其二能够经过线程池来动态地管理线程以减少没必要要的资源开销。多线程
线程执行框架启动线程
将要多线程执行的任务封装为一个Runnable对象,将其传给一个执行框架Executor对象, Executor从线程池中选择线程执行工做任务。框架
建立多线程框架对象调用线程执行任务
咱们一般经过Executors类的一些静态方法来实例化Executor或ThreadPoolExecutor对象:ide
好比Executor对象来执行:函数
public class ThreadTest { public static void main(String[] args) { Executor executor = Executors.newSingleThreadExecutor(); executor.execute(new MyRunnable()); } } class MyRunnable implements Runnable { @Override public void run() { System.out.println("running"); } }
好比线程池的Executor对象来执行:this
public class ThreadTest { public static void main(String[] args) { ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors .newFixedThreadPool(3); executor.execute(new MyRunnable()); } } class MyRunnable implements Runnable { @Override public void run() { System.out.println("running"); } }
Executors. newSingleThreadExecutor():一 个线程死掉后,自动从新建立后一个新的线程,因此没有线程池的概念,不能被ThreadPoolExecutor接收;线程
Executors. newFixedThreadPool():固定数目的线程池;code
Executors. newCachedThreadPool():动态地增长和减小线程数;对象
多线程框架对象调用线程执行任务取回结果
实现了Runnable接口的执行类虽然能够在run()方法里写入执行体,可是没法返回结果值,由于run()方法是void型的,而Callable接口解决了这个问题,在继承了Callable接口的执行类中重写call()方法能够设置返回值,当Executor对象使用submit()函数提交执行类的时候会由线程池里的线程来运行,运行获得的返回值能够使用Future<V>接口来接,取得的返回值类型由V决定,Future<V>接口表示可能会获得的返回值,可是有可能报异常,所以要抛出这些异常,而后能够取得这些返回值。继承
public class ThreadTest { public static void main(String[] args) throws InterruptedException, ExecutionException { ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors .newCachedThreadPool(); MyCallable myCallable = new MyCallable(2); Future<Integer> result = executor.submit(myCallable); System.out.println(result.get()); } } class MyCallable implements Callable<Integer> { private int num; public MyCallable(int num) { this.num = num; } @Override public Integer call() throws Exception { return num * 2; } }
多线程框架对象调用线程执行任务完成第一个仍是所有完成就取回结果
使用submit()函数取回的结果不能控制任务是完成第一个仍是所有完成就取回结果,然而使用invokeAny()和invokeAll()函数便可得到这样的效果,将执行体对象放入集合中传入这两个函数,前者能够在完成任务的多线程有一个(第一个)完成时就返回结果,所以结果类型是单结果,然后者则须要等待全部执行任务的线程都执行完毕才返回结果,所以结果还是集合。接口
1.invokeAny():
public class ThreadTest { public static void main(String[] args) throws InterruptedException, ExecutionException { ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5); List<MyCallable> callables = new ArrayList<>(); for(int i=0;i<10;i++){ MyCallable myCallable = new MyCallable(i); callables.add(myCallable); } Integer res = executor.invokeAny(callables); System.out.println(res); } } class MyCallable implements Callable<Integer> { private int num; public MyCallable(int num) { this.num = num; } @Override public Integer call() throws Exception { System.out.println(Thread.currentThread().getName() + " is running"); return num * 2; } }
2.invokeAll():
public class ThreadTest { public static void main(String[] args) throws InterruptedException, ExecutionException { ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors .newFixedThreadPool(5); List<MyCallable> callables = new ArrayList<MyCallable>(); for (int i = 0; i < 10; i++) { MyCallable myCallable = new MyCallable(i); callables.add(myCallable); } List<Future<Integer>> res = executor.invokeAll(callables); for (Future<Integer> future : res) { System.out.println(future.get()); } } } class MyCallable implements Callable<Integer> { private int num; public MyCallable(int num) { this.num = num; } @Override public Integer call() throws Exception { System.out.println(Thread.currentThread().getName() + " is running"); return num * 2; } }
多线程框架对象执行定时任务
使用Executor的schedule()函数族来调度线程池中的线程来执行callable执行类对象中的call()定时任务:
public class ThreadTest { public static void main(String[] args) throws InterruptedException, ExecutionException { ScheduledExecutorService executorService = Executors .newScheduledThreadPool(2); MyCallable callable = new MyCallable(2); executorService.schedule(callable, 10, TimeUnit.SECONDS); executorService.shutdown(); } } class MyCallable implements Callable<Integer> { private int num; public MyCallable(int num) { this.num = num; } @Override public Integer call() throws Exception { System.out.println(Thread.currentThread().getName() + " is running"); return num * 2; } }