1、Runnable
Runnable是一个接口,没有返回也不能抛出异常。定义如下
public interface Runnable {
public abstract void run();
}
举个栗子,开启一个线程,休眠3秒。这里定义了一个名为OneRun类,并且实现了Runnable接口。
public class OneRun implements Runnable{
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
由于Runnable不能抛出异常,因此Thread.Sleep可能抛出的异常,只能在run方法内部处理。
public static void main(String[] args) {
Thread thread = new Thread(new OneRun());
thread.start();
}
接着在main主线程中调用thread.start()方法,开启OneRun任务的子线程。上述的栗子我们经常用到都很简单,因此不再细说。
2、Callable<V>
Callable<V>是一个泛型接口,它有返回值(返回值就是泛型V)并且能够抛出异。定义如下
public interface Callable<V> {
V call() throws Exception;
}
它比的功能比Runnable要强大很多,使用起来也更复杂。需要特别注意的是Callable的一般与线程池接口(ExecutorService)配合使用。下面举一个简单的应用栗子。
public class TwoRun implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(3000);
return "HelloWorld";
}
}
模拟耗时操作,3秒后返回HelloWorld字符串
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<String> future = executorService.submit(new TwoRun());
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
将Callable的实例woRun对象放进线程池中,它会返回一个Future对象。Future<V>也是一个泛型接口,表示一个异步运算结果。
接着通过调用Future对象的get()方法获取返回值。get()方法会一直阻塞当前线程直到Callable<V>接口的call()方法计算完成(有点类似生产者-消费者模式)。
3、总结
类别 | Runnable | Callable |
---|---|---|
返回值 | 无 | T类型 |
能否抛出异常 | 否 | 是 |
4、参考资料
https://developer.android.com/reference/java/lang/Runnable
https://developer.android.com/reference/java/util/concurrent/Callable