Java并发编程核心方法与框架-Future和Callable的使用
2017-01-09 14:08
405 查看
Callable接口与Runnable接口对比的主要优点是Callable接口可以通过Future获取返回值。但是Future接口调用get()方法取得结果时是阻塞的,如果调用Future对象的get()方法时任务尚未执行完,则调用get()方法时一直阻塞到此任务完成。如果前面的任务耗时很多,则后面的任务调用get()方法就呈阻塞状态,大大影响运行效率。主线程不能保证首先获得的是最先完成任务的返回值,这是Future的缺点。
打印结果如下:
从打印结果看,可见get()方法具有阻塞的特性。
方法submit()不仅可以传入Callable对象,还可以传入Runnable对象,submit()方法支持有返回值和无返回值。
打印结果如下:
方法isDone()无阻塞特性。
使用ExecutorService接口中的方法submit(Runnable, T result)
控制台打印结果如下:
public class MyCallable implements Callable<String> { private int age; public MyCallable(int age) { super(); this.age = age; } @Override public String call() throws Exception { TimeUnit.SECONDS.sleep(8); return "返回值 年龄是:" + age; } public static void main(String[] args) { MyCallable myCallable = new MyCallable(22); int corePoolSize = 2; int maximumPoolSize = 3; int keepAliveTime = 5; TimeUnit unit = TimeUnit.SECONDS; LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<Runnable>(); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); Future<String> future = threadPoolExecutor.submit(myCallable); try { System.out.println(System.currentTimeMillis()); String string = future.get(); System.out.println(string); System.out.println(System.currentTimeMillis()); } catch (Exception e) { e.printStackTrace(); } } }
打印结果如下:
1470904027660 返回值 年龄是:22 1470904035663
从打印结果看,可见get()方法具有阻塞的特性。
方法submit()不仅可以传入Callable对象,还可以传入Runnable对象,submit()方法支持有返回值和无返回值。
public class Run { public static void main(String[] args) { try { Runnable runnable = new Runnable() { @Override public void run() { System.out.println("打印的信息"); } }; ExecutorService executorService = Executors.newCachedThreadPool(); Future future = executorService.submit(runnable); System.out.println(future.get() + " " + future.isDone()); } catch (Exception e) { e.printStackTrace(); } } }
打印结果如下:
打印的信息 null true
方法isDone()无阻塞特性。
使用ExecutorService接口中的方法submit(Runnable, T result)
public class User { private String username; private String password; //省略getter setter } public class MyRunnable implements Runnable { private User user; public MyRunnable(User user) { super(); this.user = user; } @Override public void run() { try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } user.setUsername("admin"); user.setPassword("123456"); } } public class Main { FutureTask task; public static void main(String[] args) { try { User user = new User(); MyRunnable myRunnable = new MyRunnable(user); int corePoolSize = 10; int maximumPoolSize = 10; int keepAliveTime = 10; TimeUnit unit = TimeUnit.SECONDS; LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>(); ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); Future<User> future = executor.submit(myRunnable, user); System.out.println(System.currentTimeMillis()); System.out.println(user.getUsername() + "-" + user.getPassword()); user = future.get(); System.out.println(user.getUsername() + "-" + user.getPassword()); System.out.println(System.currentTimeMillis()); } catch (Exception e) { e.printStackTrace(); } } }
控制台打印结果如下:
1470908214853 null-null admin-123456 1470908216855
相关文章推荐
- Java并发编程核心方法与框架-CountDownLatch的使用
- Java并发编程核心方法与框架-ScheduledExecutorService的使用
- Java并发编程核心方法与框架-CyclicBarrier的使用
- Java并发编程核心方法与框架-Executors的使用
- Java并发编程核心方法与框架-exchanger的使用
- Java并发编程核心方法与框架-TheadPoolExecutor的使用
- Java并发编程核心方法与框架-TheadPoolExecutor的使用
- Java并发编程核心方法与框架-ExecutorService的使用
- Java并发编程核心方法与框架-ScheduledExecutorService的使用
- Java并发编程核心方法与框架-Semaphore的使用
- Java并发编程核心方法与框架-CompletionService的使用
- Java并发编程核心方法与框架-phaser的使用
- Java并发编程核心方法与框架-Semaphore的使用
- Java并发编程核心方法与框架-CountDownLatch的使用
- Java并发编程核心方法与框架-Executors的使用
- Java并发编程核心方法与框架-phaser的使用
- Java并发编程核心方法与框架-CompletionService的使用
- Java并发编程核心方法与框架-ExecutorService的使用
- Java并发编程核心方法与框架-CyclicBarrier的使用
- Java并发编程核心方法与框架-Fork-Join分治编程(二)