在Java中设计并发线程时,使用Runnable接口和Callable接口有什么区别,为什么你会选择其中一个而不是另一个?
当前回答
Callable和Runnable之间的区别如下:
在JDK 5.0中引入了Callable,而在JDK 1.0中引入了Runnable 可调用对象有call()方法,而Runnable有run()方法。 可调用对象有返回值的call方法,而可运行对象有不返回任何值的run方法。 调用方法可以抛出检查异常,但运行方法不能抛出检查异常。 可调用的使用submit()方法放入任务队列,可运行的使用execute()方法放入任务队列。
其他回答
请看这里的解释。
Callable接口类似于 可运行的,因为两者都是设计出来的 对于实例为的类 可能由另一个人执行 线程。然而,Runnable则不然 返回结果,且不能抛出 检查异常。
除了所有其他答案:
我们不能传递/使用Callable到单独的线程执行,即Callable只能在执行器框架中使用。 但是,Runnable可以传递给一个单独的线程执行(new thread (new CustomRunnable())),也可以在Executor Framework中使用。
我在另一篇博客中发现了这一点,可以更好地解释这些差异:
虽然这两个接口都是由希望在不同的执行线程中执行的类实现的,但这两个接口之间有一些区别:
Callable<V>实例返回类型为V的结果,而Runnable实例则不会。 Callable<V>实例可能会抛出受控异常,而Runnable实例则不会
Java的设计者觉得有必要扩展Runnable接口的功能,但他们不想影响Runnable接口的使用,这可能就是为什么他们在Java 1.5中使用一个名为Callable的单独接口,而不是修改已经存在的Runnable的原因。
当我们使用Executer框架时,Runnable (vs) Callable就出现了。
ExecutorService是Executor的子接口,它接受可运行任务和可调用任务。
早期的多线程可以使用Interface RunnableSince 1.0实现,但这里的问题是在完成线程任务后,我们无法收集线程信息。为了收集数据,我们可以使用静态字段。
使用不同的线程收集每个学生的数据。
static HashMap<String, List> multiTasksData = new HashMap();
public static void main(String[] args) {
Thread t1 = new Thread( new RunnableImpl(1), "T1" );
Thread t2 = new Thread( new RunnableImpl(2), "T2" );
Thread t3 = new Thread( new RunnableImpl(3), "T3" );
multiTasksData.put("T1", new ArrayList() ); // later get the value and update it.
multiTasksData.put("T2", new ArrayList() );
multiTasksData.put("T3", new ArrayList() );
}
为了解决这个问题,他们引入了Callable<V>Since 1.5,它返回一个结果并可能引发异常。
单一抽象方法:可调用接口和可运行接口都有一个单一的抽象方法,这意味着它们可以在java 8的lambda表达式中使用。 可运行的{ 公共无效运行(); } 可调用的<对象> { 公共对象调用()抛出异常; }
有几种不同的方法可以将任务委托给ExecutorService执行。
execute(可运行任务):void将新线程装箱,但不会阻塞主线程或调用线程,因为此方法返回void。 未来提交(可调用< ? >):< ?未来>,提交(Runnable): < ?当你使用future.get()时,>板条箱新线程并阻塞主线程。
在Executor框架中使用可运行、可调用接口的例子。
class CallableTask implements Callable<Integer> {
private int num = 0;
public CallableTask(int num) {
this.num = num;
}
@Override
public Integer call() throws Exception {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " : Started Task...");
for (int i = 0; i < 5; i++) {
System.out.println(i + " : " + threadName + " : " + num);
num = num + i;
MainThread_Wait_TillWorkerThreadsComplete.sleep(1);
}
System.out.println(threadName + " : Completed Task. Final Value : "+ num);
return num;
}
}
class RunnableTask implements Runnable {
private int num = 0;
public RunnableTask(int num) {
this.num = num;
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " : Started Task...");
for (int i = 0; i < 5; i++) {
System.out.println(i + " : " + threadName + " : " + num);
num = num + i;
MainThread_Wait_TillWorkerThreadsComplete.sleep(1);
}
System.out.println(threadName + " : Completed Task. Final Value : "+ num);
}
}
public class MainThread_Wait_TillWorkerThreadsComplete {
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("Main Thread start...");
Instant start = java.time.Instant.now();
runnableThreads();
callableThreads();
Instant end = java.time.Instant.now();
Duration between = java.time.Duration.between(start, end);
System.out.format("Time taken : %02d:%02d.%04d \n", between.toMinutes(), between.getSeconds(), between.toMillis());
System.out.println("Main Thread completed...");
}
public static void runnableThreads() throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<?> f1 = executor.submit( new RunnableTask(5) );
Future<?> f2 = executor.submit( new RunnableTask(2) );
Future<?> f3 = executor.submit( new RunnableTask(1) );
// Waits until pool-thread complete, return null upon successful completion.
System.out.println("F1 : "+ f1.get());
System.out.println("F2 : "+ f2.get());
System.out.println("F3 : "+ f3.get());
executor.shutdown();
}
public static void callableThreads() throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<Integer> f1 = executor.submit( new CallableTask(5) );
Future<Integer> f2 = executor.submit( new CallableTask(2) );
Future<Integer> f3 = executor.submit( new CallableTask(1) );
// Waits until pool-thread complete, returns the result.
System.out.println("F1 : "+ f1.get());
System.out.println("F2 : "+ f2.get());
System.out.println("F3 : "+ f3.get());
executor.shutdown();
}
}
Java功能接口
它是一种与函数式编程相匹配的接口命名约定
//Runnable
interface Runnable {
void run();
}
//Action - throws exception
interface Action {
void run() throws Exception;
}
//Consumer - consumes a value/values, throws exception
//BiConsumer,
interface Consumer1<T> {
void accept(T t) throws Exception;
}
//Callable - return result, throws exception
interface Callable<R> {
R call() throws Exception;
}
//Supplier - returns result, throws exception
interface Supplier<R> {
R get() throws Exception;
}
//Predicate - consumes a value/values, returns true or false, throws exception
interface Predicate1<T> {
boolean test(T t) throws Exception;
}
//Function - consumes a value/values, returns result, throws exception
//BiFunction, Function3...
public interface Function1<T, R> {
R apply(T t) throws Exception;
}
...
//Executor
public interface Executor {
void execute(Runnable command);
}
【快速闭包命名】
推荐文章
- 如何格式化Joda-Time DateTime仅为mm/dd/yyyy?
- 如何在POM.xml中引用环境变量?
- 如何在android中复制一个文件?
- 将整数转换为字符串,以逗号表示千
- 接口方法的最终参数-有什么意义?
- 每n秒运行特定代码
- Java中的@UniqueConstraint注释
- 如何在清洁模式下运行eclipse ?如果我们这样做会发生什么?
- 获取java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory异常
- Java中的正则表达式命名组
- c#和Java的主要区别是什么?
- 什么是NullPointerException,我如何修复它?
- 在Java中使用“final”修饰符
- 无法在Flutter上找到捆绑的Java版本
- 如何在Kotlin解析JSON ?