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