并发编程Future and Callable
来源:互联网 发布:general yoast seo 编辑:程序博客网 时间:2024/05/16 18:15
并发编程Future and Callable
目录:
1、Future及Callable基本介绍:
2、主要方法介绍:
3、Callable与Runnable的主要区别:
4、示例代码及运行结果:
1、Future及Callable基本介绍:
Future接口:
Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。
继承关系:
java.util.concurrent.Future<V>:V——get方法所返回的结果类型
使用原因:
获得Callable接口产生的返回值,以便进行后期的处理。
Callable接口:
返回结果并且可能抛出异常的任务。实现者定义了一个不带任何参数的叫做 call 的方法。
继承关系:
java.util.concurrent.Callable<V>:V——call方法的结果类型
使用原因:
使得线程可以产生返回值。
2、主要方法介绍:
Future接口:
boolean cancel(boolean mayInterruptIfRunning):如果线程正在运行则是否中断正在运行的线程,在代码中需要使用if(Thread.currentThread().isInterrupted())进行配合,结果返回true表示成功发送取消任务的命令,无阻塞特性;
V get():用于获得Callable的返回值,具有阻塞特性;
V get(long timeout TimeUnit unit):在指定的最大时间内等待获得返回值,超过最大等待时间,则抛出TimeoutException异常,具有阻塞特性;
boolean isCancelled():如果在任务正常完成前将其取消,则返回true,无阻塞特性;
boolean isDone():如果任务已完成,则返回true,无阻塞特性;
Callable接口:
V call():计算结果,如果无法计算结果,则抛出一个异常;
ExecutorService接口:
void shutdown():执行以前提交的任务,但不再接受提交的新任务。通常shutdown后调用awaitTermination,awaitTermination会阻塞当前线程,等待以前提交的任务执行完,然后才继续向下执行;
<T> Future<T> submit(Callable<T> task):提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future,说明submit()方法支持有返回值的功能;
<T> Future<T> submit(Callable<T> task, T result):第二个参数result可以作为执行结果的返回值,而不需要使用get()方法来进行获得;
boolean awaitTermination(long timeout, TimeUnit unit):当等待超过设定时间时,会监测ExecutorService是否已经关闭,若关闭则返回true,否则返回false,具有阻塞特性;
Future<?> submit(Runnable task):提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future,说明submit()方法支持无返回值的功能;
3、Callable与Runnable的主要区别:
(1)Callable接口的call()方法可以有返回值,而Runnable接口的run()方法没有返回值;
(2)Callable接口的call()方法就可以声明抛出异常,而Runnable接口的run()方法不可以声明抛出异常;
(3)执行完Callable接口中的任务后,返回值是通过Future接口进行获得的。
4、示例代码及运行结果:
(1)工程目录图:
图4.1 工程目录图
(2)FutureAndCallableService.java
package com.remoa.futureAndCallable.service;import java.text.SimpleDateFormat;public interface FutureAndCallableService { SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); void Test(); }
(3)Test1MyCallable1.javapackage com.remoa.futureAndCallable.domain.callable;import com.remoa.futureAndCallable.domain.Remoa;import java.util.ArrayList;import java.util.List;import java.util.Random;import java.util.UUID;import java.util.concurrent.Callable;public class Test1MyCallable1 implements Callable<List<Remoa>> { @Override public List<Remoa> call() throws Exception { Thread.sleep(500); List<Remoa> list = new ArrayList<>(); Random random = new Random(); for (int i = 0; i < 5; i++) { String uuid = UUID.randomUUID().toString().substring(0,10); Remoa remoa = new Remoa(); remoa.setAge(random.nextInt(29) + 1); remoa.setName("Remoa" + i); remoa.setStudentId(uuid); list.add(remoa); } return list; }}
(4)TestMyCallable2.java
package com.remoa.futureAndCallable.domain.callable;import com.remoa.futureAndCallable.domain.Remoa;import java.text.SimpleDateFormat;import java.util.*;import java.util.concurrent.Callable;public class Test1MyCallable2 implements Callable<List<Remoa>> { private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @Override public List<Remoa> call() throws Exception { Thread.sleep(500); List<Remoa> list = new ArrayList<>(); Random random = new Random(); for (int i = 0; i < 5; i++) { if(Thread.currentThread().isInterrupted()){ System.out.println(Thread.currentThread().getName() + "中断时间为:" + simpleDateFormat.format(new Date())); throw new InterruptedException(); } String uuid = UUID.randomUUID().toString().substring(0,10); Remoa remoa = new Remoa(); remoa.setAge(random.nextInt(29) + 1); remoa.setName("Remoa" + i); remoa.setStudentId(uuid); list.add(remoa); } return list; }}
(5)Test1ServcieImp.javapackage com.remoa.futureAndCallable.service.Imp;import com.remoa.futureAndCallable.domain.callable.Test1MyCallable1;import com.remoa.futureAndCallable.domain.callable.Test1MyCallable2;import com.remoa.futureAndCallable.domain.Remoa;import com.remoa.futureAndCallable.service.FutureAndCallableService;import java.util.Date;import java.util.List;import java.util.concurrent.*;/** * cancel中断线程方法的测试 */public class Test1ServiceImp implements FutureAndCallableService { public Test1ServiceImp(){ String date = SIMPLE_DATE_FORMAT.format(new Date()); System.out.println(date + "开始进行cancel中断线程方法的测试"); } @Override public void Test() { Test1MyCallable1 test1MyCallable1 = new Test1MyCallable1(); Test1MyCallable2 test1MyCallable2 = new Test1MyCallable2(); /* int corePoolSize:池中保存的线程数,包括空闲线程 int maximumPoolSize:池中允许的最大线程数 long keepAliveTime:当线程数大于池中保存的线程数时,此为终止多余的空闲线程等待新任务的最长时间 TimeUnit unit:keepAliveTime参数的时间单位 BlockingQueue<Runnable> workQueue:执行前用于保持任务的队列,此队列仅保持由execute方法提交的Runnable任务 */ ExecutorService executorService = new ThreadPoolExecutor(10, 20, 5, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>()); try { Future<List<Remoa>> future1 = executorService.submit(test1MyCallable1); System.out.println("(1)先执行具有阻塞特性的get方法:"); for (int i = 0; i < future1.get().size(); i++) { System.out.println(future1.get().get(i)); } System.out.println("成功发送任务取消的命令了吗?" + future1.cancel(true)); System.out.println("任务是在正常完成前将其取消的吗?" + future1.isCancelled()); } catch (InterruptedException e) { System.out.println("Future1抛出了中断异常"); } catch (ExecutionException e) { System.out.println("Future1抛出了执行异常"); }finally { try { Thread.sleep(1000); System.out.println("--------------------"); Future<List<Remoa>> future2 = executorService.submit(test1MyCallable1); System.out.println("(2)先执行发送任务取消的命令:"); System.out.println("成功发送任务取消的命令了吗?" + future2.cancel(true)); System.out.println("任务是在正常完成前将其取消的吗?" + future2.isCancelled()); System.out.println("后执行具有阻塞特性的get方法:"); System.out.println(future2.get().size()); for (int i = 0; i < future2.get().size(); i++) { System.out.println(future2.get().get(i)); } } catch (InterruptedException e) { System.out.println("Future2抛出了中断异常"); } catch (ExecutionException e) { System.out.println("Future2抛出了执行异常"); } catch(CancellationException e){ System.out.println("Future2抛出了取消任务异常"); }finally{ try { Thread.sleep(1000); System.out.println("--------------------"); Future<List<Remoa>> future3 = executorService.submit(test1MyCallable2); System.out.println("(3)配合isInterrupted一起使用"); System.out.println("先执行发送任务取消的命令,cancel方法参数选择为false:"); //发送取消的命令,发送成功返回true,但是方法参数传的是false,则线程不会中断会一直执行 System.out.println("成功发送任务取消的命令了吗?" + future3.cancel(false)); System.out.println("任务是在正常完成前将其取消的吗?" + future3.isCancelled()); System.out.println("后执行具有阻塞特性的get方法:"); for (int i = 0; i < future3.get().size(); i++) { System.out.println(future3.get().get(i)); } } catch (InterruptedException e) { System.out.println("Future3抛出了中断异常"); } catch (ExecutionException e) { System.out.println("Future3抛出了执行异常"); } catch(CancellationException e){ System.out.println("Future3抛出了取消任务异常"); }finally { try { Thread.sleep(1000); System.out.println("--------------------"); Future<List<Remoa>> future4 = executorService.submit(test1MyCallable2); System.out.println("(4)配合isInterrupted一起使用"); System.out.println("先执行发送任务取消的命令,cancel方法参数选择为true:"); //设置了sleep睡眠时间,则线程已经跑完,中断命令不再起作用,将返回false Thread.sleep(800); System.out.println("成功发送任务取消的命令了吗?" + future4.cancel(true)); System.out.println("任务是在正常完成前将其取消的吗?" + future4.isCancelled()); System.out.println("后执行具有阻塞特性的get方法:"); for (int i = 0; i < future4.get().size(); i++) { System.out.println(future4.get().get(i)); } } catch (InterruptedException e) { System.out.println("Future4抛出了中断异常"); } catch (ExecutionException e) { System.out.println("Future4抛出了执行异常"); } } } } }}
运行结果:图4.2 测试1截图
(6)Test2MyCallable.java
package com.remoa.futureAndCallable.domain.callable;import com.remoa.futureAndCallable.domain.Remoa;import java.text.SimpleDateFormat;import java.util.*;import java.util.concurrent.Callable;public class Test2MyCallable implements Callable<Remoa>{ private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @Override public Remoa call() throws Exception { System.out.println(simpleDateFormat.format(new Date())); Thread.sleep(10000); Remoa remoa = new Remoa(); remoa.setName("Remoa"); remoa.setAge(21); remoa.setStudentId("3114005847"); return remoa; }}
(7)Test2ServiceImp.javapackage com.remoa.futureAndCallable.service.Imp;import com.remoa.futureAndCallable.domain.Remoa;import com.remoa.futureAndCallable.domain.callable.Test2MyCallable;import com.remoa.futureAndCallable.service.FutureAndCallableService;import java.util.Date;import java.util.concurrent.*;/** * Future.get(long timeout, TimeUnit unit)方法的测试 */public class Test2ServiceImp implements FutureAndCallableService { public Test2ServiceImp(){ String date = SIMPLE_DATE_FORMAT.format(new Date()); System.out.println(date + "开始进行get(long timeout, TimeUnit unit)方法的测试"); } @Override public void Test() { Test2MyCallable myCallable = new Test2MyCallable(); ExecutorService executorService = new ThreadPoolExecutor(10, 20, 5, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); Future<Remoa> future = executorService.submit(myCallable); System.out.println("设置在五秒中内等待获得返回值:"); try { System.out.println(future.get(5,TimeUnit.SECONDS)); } catch (InterruptedException e) { System.out.println("Future抛出了线程中断异常"); } catch (ExecutionException e) { System.out.println("Future抛出了执行异常"); } catch (TimeoutException e) { System.out.println("Future抛出了超时异常"); } }}
运行结果:图4.3 测试2截图
(8)Test3MyCallable.java
package com.remoa.futureAndCallable.domain.callable;import com.remoa.futureAndCallable.domain.Remoa;import java.text.SimpleDateFormat;import java.util.Date;import java.util.concurrent.Callable;public class Test3MyCallable implements Callable<Remoa> { private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private String username; private String studentId; private int age; public Test3MyCallable(String username, String studentId, int age){ this.username = username; this.studentId = studentId; this.age = age; } @Override public Remoa call() throws Exception { System.out.println(simpleDateFormat.format(new Date())); Remoa remoa = new Remoa(); remoa.setName(username); remoa.setAge(age); remoa.setStudentId(studentId); return remoa; }}
(9)Test3ServiceImp.javapackage com.remoa.futureAndCallable.service.Imp;import com.remoa.futureAndCallable.domain.Remoa;import com.remoa.futureAndCallable.domain.callable.Test3MyCallable;import com.remoa.futureAndCallable.service.FutureAndCallableService;import com.remoa.futureAndCallable.service.MyRejectedExceptionHandler;import java.util.Date;import java.util.concurrent.*;/** * 自定义拒绝策略RejectedExecutionHandler接口使用的测试 */public class Test3ServiceImp implements FutureAndCallableService { public Test3ServiceImp(){ String date = SIMPLE_DATE_FORMAT.format(new Date()); System.out.println(date + "开始进行自定义拒绝策略RejectedExecutionHandler接口使用的测试"); } @Override public void Test() { ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 20, 5, TimeUnit.SECONDS, new LinkedBlockingDeque<>()); executor.setRejectedExecutionHandler(new MyRejectedExceptionHandler()); ExecutorService executorService = executor; Future<Remoa> future1 = executorService.submit(new Test3MyCallable("Remoa1", "3114005847", 21)); Future<Remoa> future2 = executorService.submit(new Test3MyCallable("Remoa2", "3114005848", 22)); Future<Remoa> future3 = executorService.submit(new Test3MyCallable("Remoa3", "3114005849", 23)); try { System.out.println(future1.get()); System.out.println(future2.get()); System.out.println(future3.get()); } catch (InterruptedException e) { System.out.println("Future1或Future2或Future3发生了中断异常"); } catch (ExecutionException e) { System.out.println("Future1或Future2或Future3发生了执行异常"); } executor.shutdown(); Future<Remoa> future4 = executorService.submit(new Test3MyCallable("Remoa4", "3114005850", 24)); try { System.out.println(future4.get()); } catch (InterruptedException e) { System.out.println("Future4发生了中断异常"); } catch (ExecutionException e) { System.out.println("Future4发生了执行异常"); } }}
(10)MyRejectedExceptionHandler.java
package com.remoa.futureAndCallable.service;import com.remoa.futureAndCallable.domain.Menu;import java.util.concurrent.FutureTask;import java.util.concurrent.RejectedExecutionHandler;import java.util.concurrent.ThreadPoolExecutor;/** * RejectedExecutionHandler其主要作用是当线程池关闭后依然后任务要执行时,可以实现一些处理。 */public class MyRejectedExceptionHandler implements RejectedExecutionHandler{ @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { System.out.println(((FutureTask)r).toString() + "被拒绝"); Menu.getMenu(); }}
运行结果:(11)Test4MyCallable.java
package com.remoa.futureAndCallable.domain.callable;import com.remoa.futureAndCallable.domain.Remoa;import java.text.SimpleDateFormat;import java.util.*;import java.util.concurrent.Callable;public class Test4MyCallable implements Callable<List<Remoa>>{ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @Override public List<Remoa> call() throws Exception { System.out.println(Thread.currentThread().getName() + ",开始执行的时间为:" + simpleDateFormat.format(new Date())); List<Remoa> list = new ArrayList<>(); Random random = new Random(); for (int i = 0; i < (random.nextInt(1000) + 10) * 100000; i++) { String uuid = UUID.randomUUID().toString().substring(0,10); Remoa remoa = new Remoa(); remoa.setAge(random.nextInt(29) + 1); remoa.setName("Remoa" + i); remoa.setStudentId(uuid); list.add(remoa); } System.out.println(Thread.currentThread().getName() + ", list's size = " + list.size()); System.out.println(Thread.currentThread().getName() + "任务结束,结束时间为:" + simpleDateFormat.format(new Date())); return list; }}
(12)Test4ServiceImp.java
package com.remoa.futureAndCallable.service.Imp;import com.remoa.futureAndCallable.domain.callable.Test4MyCallable;import com.remoa.futureAndCallable.service.FutureAndCallableService;import java.util.Date;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;/** * ExecutorService的相关方法测试 */public class Test4ServiceImp implements FutureAndCallableService { public Test4ServiceImp(){ String date = SIMPLE_DATE_FORMAT.format(new Date()); System.out.println(date + "开始进行ExecutorService的相关方法的测试"); } @Override public void Test() { ExecutorService executorService = Executors.newFixedThreadPool(3); Test4MyCallable callable = new Test4MyCallable(); try { while(true) { executorService.submit(callable); executorService.submit(callable); executorService.submit(callable); executorService.submit(callable); executorService.submit(callable); break; } executorService.shutdown(); boolean flag = executorService.awaitTermination(5, TimeUnit.HOURS); if(flag == false){ executorService.shutdownNow(); System.out.println("任务超时,未完成!"); } System.out.println("哈哈哈,执行最后的语句了"); } catch (InterruptedException e) { System.out.println("发生了中断异常。"); } }}
运行结果:图4.5 测试4截图
(13)Menu.java
package com.remoa.futureAndCallable.domain;import com.remoa.futureAndCallable.Strategy.ChooserTest;import java.util.Scanner;/** * 菜单类 */public class Menu { public static void getMenu(){ String choiceStr = ""; Scanner scanner = new Scanner(System.in); ChooserTest chooserTest = new ChooserTest(); while(!choiceStr.equals("0")) { System.out.println("-------------测试选项------------------------------------"); System.out.println("| 0、退出 |"); System.out.println("| 1、测试cancel中断线程方法 |"); System.out.println("| 2、测试get(long timeout, TimeUnit unit)方法 |"); System.out.println("| 3、测试自定义拒绝策略RejectedExecutionHandler接口的使用 |"); System.out.println("| 4、测试ExecutorService的相关方法 |"); System.out.println("--------------------------------------------------------"); System.out.print("请输入您的选择:"); choiceStr = scanner.nextLine(); chooserTest.chooseTestDemo(choiceStr); } }}
运行结果:图4.6 菜单选项截图
(14)Remoa.java
package com.remoa.futureAndCallable.domain;/** * Remoa实体类 */public class Remoa { private String name; private String studentId; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getStudentId() { return studentId; } public void setStudentId(String studentId) { this.studentId = studentId; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Remoa{" + "name='" + name + '\'' + ", studentId='" + studentId + '\'' + ", age=" + age + '}'; }}
(15)ChooserTest.javapackage com.remoa.futureAndCallable.Strategy;import com.remoa.futureAndCallable.service.*;import com.remoa.futureAndCallable.service.Imp.Test1ServiceImp;import com.remoa.futureAndCallable.service.Imp.Test2ServiceImp;import com.remoa.futureAndCallable.service.Imp.Test3ServiceImp;import com.remoa.futureAndCallable.service.Imp.Test4ServiceImp;/** * 测试方法选择器 */public class ChooserTest { FutureAndCallableService futureAndCallableService = null; public void chooseTestDemo(String chooseStr){ switch(chooseStr){ case "0": System.exit(0); break; case "1": futureAndCallableService = new Test1ServiceImp(); break; case "2": futureAndCallableService = new Test2ServiceImp(); break; case "3": futureAndCallableService = new Test3ServiceImp(); break; case "4": futureAndCallableService = new Test4ServiceImp(); break; default: System.out.println("You offer an invalid number of choices!Please try again or input '0' to exit"); break; } futureAndCallableService.Test(); }}
(16)FutureAndCallableAction.javapackage com.remoa.futureAndCallable.action;import com.remoa.futureAndCallable.domain.Menu;/** * 测试入口类 */public class FutureAndCallableAction { public static void main(String[] args) { Menu.getMenu(); }}
- 并发编程Future and Callable
- Java并发编程:Callable、Future
- 并发编程:Callable、Future、FutureTask
- java并发编程(8)--callable&Future
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Java并发编程:Callable、Future和FutureTask
- Python:利用内建函数将字符串转化为整数
- C# StringBuider,字符串拼接工具类
- 为什么函数可以返回unique_ptr
- linux操作命令大全
- 【ORACLE】物化视图相关元数据视图字段说明
- 并发编程Future and Callable
- horizon登录过程分析(juno)
- 移动端web开发click touch tap区别
- spring的配置文件信息
- 数据结构--内排序
- java学习笔记
- 网络爬虫基本原理
- python argparse模块
- javaEE基础篇,day0:知识点归纳