摘要:线程执行框架启动线程将要多线程执行的任务封装为一个对象将其传给一个执行框架对象从线程池中选择线程执行工作任务。
为什么需要执行框架呢?
使用一般的new方法来创建线程有什么问题呢?一般的new线程的方式一般要给出一个实现了Runnable接口的执行类,在其中重写run()方法,然后再在将这个执行类的对象传给线程以完成初始化,这个过程中线程的定义和执行过程其实是杂糅在一起了,而且每次new一个新的线程出来在资源上很有可能会产生不必要的消耗,因此我们通过多线程执行框架来解决这两个问题,其一可以分离线程的定义和执行过程,其二可以通过线程池来动态地管理线程以减小不必要的资源开销。
线程执行框架启动线程
将要多线程执行的任务封装为一个Runnable对象,将其传给一个执行框架Executor对象, Executor从线程池中选择线程执行工作任务。
创建多线程框架对象调用线程执行任务
我们通常通过Executors类的一些静态方法来实例化Executor或ThreadPoolExecutor对象:
比如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对象来执行:
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():固定数目的线程池;
Executors. newCachedThreadPool():动态地增加和减少线程数;
多线程框架对象调用线程执行任务取回结果
实现了Runnable接口的执行类虽然可以在run()方法里写入执行体,但是无法返回结果值,因为run()方法是void型的,而Callable接口解决了这个问题,在继承了Callable接口的执行类中重写call()方法可以设置返回值,当Executor对象使用submit()函数提交执行类的时候会由线程池里的线程来运行,运行得到的返回值可以使用Future
public class ThreadTest { public static void main(String[] args) throws InterruptedException, ExecutionException { ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors .newCachedThreadPool(); MyCallable myCallable = new MyCallable(2); Futureresult = executor.submit(myCallable); System.out.println(result.get()); } } class MyCallable implements Callable { 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); Listcallables = 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 { 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); Listcallables = new ArrayList (); for (int i = 0; i < 10; i++) { MyCallable myCallable = new MyCallable(i); callables.add(myCallable); } List > res = executor.invokeAll(callables); for (Future future : res) { System.out.println(future.get()); } } } class MyCallable implements Callable { 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{ 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; } }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/64616.html
摘要:线程可以被称为轻量级进程。一个守护线程是在后台执行并且不会阻止终止的线程。其他的线程状态还有,和。上下文切换是多任务操作系统和多线程环境的基本特征。在的线程中并没有可供任何对象使用的锁和同步器。 原文:Java Multi-Threading and Concurrency Interview Questions with Answers 翻译:并发编程网 - 郑旭东 校对:方腾飞 多...
摘要:多线程和并发问题是技术面试中面试官比较喜欢问的问题之一。线程可以被称为轻量级进程。一个守护线程是在后台执行并且不会阻止终止的线程。其他的线程状态还有,和。上下文切换是多任务操作系统和多线程环境的基本特征。 多线程和并发问题是 Java 技术面试中面试官比较喜欢问的问题之一。在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题。(...
摘要:整个包,按照功能可以大致划分如下锁框架原子类框架同步器框架集合框架执行器框架本系列将按上述顺序分析,分析所基于的源码为。后,根据一系列常见的多线程设计模式,设计了并发包,其中包下提供了一系列基础的锁工具,用以对等进行补充增强。 showImg(https://segmentfault.com/img/remote/1460000016012623); 本文首发于一世流云专栏:https...
摘要:大多数待遇丰厚的开发职位都要求开发者精通多线程技术并且有丰富的程序开发调试优化经验,所以线程相关的问题在面试中经常会被提到。掌握了这些技巧,你就可以轻松应对多线程和并发面试了。进入等待通行准许时,所提供的对象。 最近看到网上流传着,各种面试经验及面试题,往往都是一大堆技术题目贴上去,而没有答案。 不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题。Java语言一个重要的特点就...
摘要:一使用线程池的好处线程池提供了一种限制和管理资源包括执行一个任务。每个线程池还维护一些基本统计信息,例如已完成任务的数量。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。使用无界队列作为线程池的工作队列会对线程池带来的影响与相同。 历史优质文章推荐: Java并发编程指南专栏 分布式系统的经典基础理论 可能是最漂亮的Spring事务管理详解 面试中关于Java虚拟机(jvm)的问...
阅读 1120·2021-11-25 09:43
阅读 1642·2021-09-13 10:25
阅读 2596·2021-09-09 11:38
阅读 3403·2021-09-07 10:14
阅读 1716·2019-08-30 15:52
阅读 642·2019-08-30 15:44
阅读 3573·2019-08-29 13:23
阅读 1975·2019-08-26 13:33