Callable接口与Runnable接口对比的主要优点是Callable接口可以通过Future获取返回值。但是Future接口调用get()方法取得结果时是阻塞的,如果调用Future对象的get()方法时任务尚未执行完,则调用get()方法时一直阻塞到此任务完成。如果前面的任务耗时很多,则后面的任务调用get()方法就呈阻塞状态,大大影响运行效率。主线程不能保证首先获得的是最先完成任务的返回值,这是Future的缺点。

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并发编程核心方法与框架-Future和Callable的使用的更多相关文章

  1. Java并发编程核心方法与框架-CountDownLatch的使用

    Java多线程编程中经常会碰到这样一种场景:某个线程需要等待一个或多个线程操作结束(或达到某种状态)才开始执行.比如裁判员需要等待运动员准备好后才发送开始指令,运动员要等裁判员发送开始指令后才开始比赛 ...

  2. Java并发编程核心方法与框架-Fork-Join分治编程(一)

    在JDK1.7版本中提供了Fork-Join并行执行任务框架,它的主要作用是把大任务分割成若干个小任务,再对每个小任务得到的结果进行汇总,这种开发方法也叫做分治编程,可以极大地利用CPU资源,提高任务 ...

  3. Java并发编程核心方法与框架-CompletionService的使用

    接口CompletionService的功能是以异步的方式一边生产新的任务,一边处理已完成任务的结果,这样可以将执行任务与处理任务分离.使用submit()执行任务,使用take取得已完成的任务,并按 ...

  4. Java并发编程核心方法与框架-TheadPoolExecutor的使用

    类ThreadPoolExecutor最常使用的构造方法是 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAli ...

  5. Java并发编程核心方法与框架-Semaphore的使用

    Semaphore中文含义是信号.信号系统,这个类的主要作用就是限制线程并发数量.如果不限制线程并发数量,CPU资源很快就会被耗尽,每个线程执行的任务会相当缓慢,因为CPU要把时间片分配给不同的线程对 ...

  6. Java并发编程核心方法与框架-ScheduledExecutorService的使用

    类SchedukedExecutorService的主要作用是可以将定时任务与线程池功能结合. 使用Callable延迟运行(有返回值) public class MyCallableA implem ...

  7. Java并发编程核心方法与框架-ExecutorService的使用

    在ThreadPoolExecutor中使用ExecutorService中的方法 方法invokeAny()和invokeAll()具有阻塞特性 方法invokeAny()取得第一个完成任务的结果值 ...

  8. Java并发编程核心方法与框架-Executors的使用

    合理利用线程池能够带来三个好处 降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行. 提高线程的可管理性.线程是稀 ...

  9. Java并发编程核心方法与框架-phaser的使用

    arriveAndAwaitAdvance()方法 arriveAndAwaitAdvance()作用是当前线程已经到达屏障,在此等待一段时间,等条件满足后继续向下一个屏障执行. public cla ...

随机推荐

  1. Unable to find element on closed window (WARNING: The server did not provide any stacktrace information)

    当你的selenium WebDriver 启动IE11报这个错时:Unable to find element on closed window (WARNING: The server did n ...

  2. iOS的nil,Null,NSNull的使用

    今天做项目时,在数组里面取值时,发现里面有NSNull的对象,然后用数组里面对应的对象赋值时出现各种问题,总是报错.后面经过研究和查资料,总算解决了这一问题. nil用来给对象赋值(Objective ...

  3. Numpy 用法小结

    1.  asarray 函数 可以将输入数据转化为矩阵格式. 输入数据可以是(列表,元组,列表的列表,元组的元组,元组的列表等这些数组形式). >>> asarray([(1,2,3 ...

  4. css-关于absolute和relative的一些笔记

    根据张鑫旭老师的博客,一些笔记留作备忘 1.position:absolute 具有包裹性--包裹性换种说法就是让元素inline-block化,例如一个div标签默认宽度是100%显示的,但是一旦被 ...

  5. NOIP2013

    DAY1 转圈游戏 列出式子(x+km)%n,快速幂. // codevs3285 #include<algorithm> #include<iostream> #includ ...

  6. BZOJ1057 [ZJOI2007]棋盘制作

    Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源 于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应 ...

  7. Subime学习记录

    一.快捷键 注:快捷键这种东西没有必要刻意去记,自己需要就去查查,经常用的自然熟了,关键是时刻保持提高效率的意识,才会主动去发现快捷键. 1.Ctrl + F:查找 2.F12:根据函数定位函数声明( ...

  8. list去除并且把值相加

    package list; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import ja ...

  9. RabbitMQ 通过记日志来看routingkey

    RoutingKey 每个项目都需要记录日志,日志则一般会分为多种级别,常见的是 Info.debug.warn.Error 对于前三种日志,在项目运行中会产生大量的消息,但是一般多数情况下是不会用到 ...

  10. ExceptionLess异常日志收集框架-1

    哈哈,中秋和代码更配哦,不知不觉一年过半了,祝园友们中秋快乐 前一阵子在博客园看到了一篇博文 http://www.cnblogs.com/savorboard/p/exceptionless.htm ...