runable的异步是不需要返回,主线程执行后续代码,主线程可以直接结束--由此体现异步
callable的异步是可以返回,主线程需要等待子线程返回,一般开启多个子线程--由此体现异步
不同点 | Callable | Runnable |
方法 | V call() throws Exception | run() |
返回值 | V call() 有返回值 | void run() 没有返回值 |
异常 | call() 可以抛出受检查的异常 | run() 不能抛出异常 |
启动 | 1、使Thread 来包装,使用start() 启动 2、提交给 线程池 ExecuteService.submit() 启动 |
1、使Thread 来包装,使用start() 启动 2、提交给 线程池 ExecuteService.submit() 和execute() 启动
注意:execute() 只接收Runnable实现类,且没有返回值 |
class CallableImpl implements Callable {
private int age;
public CallableImpl(int age) {
this.age = age;
}
// 具体逻辑在这里实现,并有一个返回值
public Object call() throws Exception {
Thread.currentThread().sleep(new Random().nextInt(1000));
String ss="";
if (age < 0) {
ss="age = " + age + ", 输入年龄有误";
} else if (age < 20) {
ss="age = " + age + ", 你好,年轻人";
} else if (age < 40) {
ss= "age = " + age + ", 你好,中年人";
} else {
ss= "age = " + age + ", 你好,老年人";
}
System.out.println(ss);
return ss;
}
}
public class CallableTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 建立一个线程池
ExecutorService exc = Executors.newFixedThreadPool(3);
// 存放返回的结果
List
for (int i = -10; i < 50; i += 3) {
CallableImpl call = new CallableImpl(i);
// 执行callable的call方法,并有返回值
Future
futures.add(future);
}
System.out.println("等待结果:");
for (Future
// 这里调用get()方法会阻塞当前线程,直到得到返回结果
System.out.println("----------- "+future.get());
// if (future.isDone()) {
// System.out.println(future.get());
// } else {
// System.out.println("Future result is not yet complete");
// }
}
System.out.println("结束...");
//Thread.currentThread().sleep(1000*30);
exc.shutdown();
}
}
结果:
等待结果:
age = -10, 输入年龄有误
----------- age = -10, 输入年龄有误
age = -4, 输入年龄有误
age = -1, 输入年龄有误
age = 2, 你好,年轻人
age = -7, 输入年龄有误
----------- age = -7, 输入年龄有误
----------- age = -4, 输入年龄有误
----------- age = -1, 输入年龄有误
----------- age = 2, 你好,年轻人
age = 11, 你好,年轻人
age = 5, 你好,年轻人
----------- age = 5, 你好,年轻人
age = 8, 你好,年轻人
----------- age = 8, 你好,年轻人
----------- age = 11, 你好,年轻人
age = 17, 你好,年轻人
age = 14, 你好,年轻人
----------- age = 14, 你好,年轻人
----------- age = 17, 你好,年轻人
age = 26, 你好,中年人
age = 23, 你好,中年人
age = 20, 你好,中年人
----------- age = 20, 你好,中年人
----------- age = 23, 你好,中年人
----------- age = 26, 你好,中年人
age = 35, 你好,中年人
age = 32, 你好,中年人
age = 41, 你好,老年人
age = 29, 你好,中年人
----------- age = 29, 你好,中年人
----------- age = 32, 你好,中年人
----------- age = 35, 你好,中年人
age = 38, 你好,中年人
----------- age = 38, 你好,中年人
----------- age = 41, 你好,老年人
age = 44, 你好,老年人
----------- age = 44, 你好,老年人
age = 47, 你好,老年人
----------- age = 47, 你好,老年人
结束...
public class LiftOff implements Runnable {
protected int countDown = 10;
private static int taskCount = 0;
private final int id = taskCount++;
public LiftOff() {
}
public LiftOff(int countDown) {
this.countDown = countDown;
}
public String status() {
return "#" + id + "(" + (countDown > 0 ? countDown : "LiftOff! ") + ")";
}
@Override
public void run() {
while (countDown-- > 0) {
System.out.print(status());
Thread.yield();
}
System.out.println();
}
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(1);
for (int i = 0; i < 5; i++) {
exec.execute(new LiftOff());
}
exec.shutdown();
}
}
注意ExecutorService 在Callable中使用的是submit(), 在Runnable中使用的是 execute()。