【问题标题】:What is the difference when submitting, class implementing Callable and class which doesn't, to the executor service将实现 Callable 的类和不实现 Callable 的类提交给 executor 服务有什么区别
【发布时间】:2016-10-12 10:37:47
【问题描述】:

我是线程主题的新手。我需要将任务异步提交给执行器服务,并且还需要取回响应。我尝试过以下示例。

案例一:

public class Task implements Callable<Integer> {
    Integer i;
    public Task(Integer i){
        this.i = i;
    }
    @Override
    public Integer call(){
        doTask();
    }
    public Integer doTask(){
        syso(i);
        return i;
    }
}

public class ExecuteTask(){
    public void static main (String [] args){
        ExecutorService service = Executor.newCachedTheadPool();

        for(int i = 0; int <10; i++) {
            service.sumbit(new Task(i).doTask());
        }
    }
}
Output: 0,1,2,3,4,7,9,5,8,6 (expected)

案例 2:

public class Task {
    Integer i;
    public Task(Integer i){
        this.i = i;
    }
    public Integer doTask(){
        syso(i);
        return i;
    }
}

public class ExecuteTask(){
    int i;
    public void static main (String [] args){
        ExecutorService service = Executor.newCachedTheadPool();

        for(i = 0; int <10; i++) {
            service.sumbit(new Callable<Integer>(){
                @Override
                public Integer call() {
                    Integer int = new Task(i).doTask();
                    return int;
                }
            });
        }
    }
}
Output: 1,3,3,6,6,6,10,10,10,10 (not expected)

我的问题是为什么我在上述两种情况下看到不同的结果。如果我不将 i 声明为全局变量,我将遇到错误。

我在封闭范围内定义的局部变量必须是最终的或有效的最终

主要是因为这个,我得到了意外的输出,因为其他线程可能在奴隶打印它时修改了 I 的值?实时任务类是一个更复杂的对象(它具有从服务获取数据并将其写入数据库的逻辑),如果任务类没有实现 Callable,我将如何处理?

我提交给执行者的实例/任务是否必须实现 Callable(为此我需要要求任务类的所有者明确实现 Callable)。

或者在运行时创建匿名类并在 call() 中添加实例化任务类也是正确的做法?

【问题讨论】:

  • 我没有传递其他东西来提交,我已经在 for 循环中明确声明了 Callable 匿名类。我的代码将编译,并且仅在不将 i 声明为全局变量时才提到该错误。
  • 好的。第一个 sn-p:Task 实现了 Callable,但没有覆盖 call()。所以无法编译。使用不存在的 Executor.newCachedTheadPool()。第二个sn-p:调用一个不存在的方法syso。第三个 sn-p:使用名为 int 的未定义变量。不可能编译。尝试使用来自匿名类的非最终变量。无法编译。
  • 请尝试获取问题的上下文并尝试回答我的问题。我没有在这里复制粘贴我的实际代码(所以它只是 int 不是对象)......并使用 syso 作为 System.out.println 的快捷方式。是的,同意我首先错过了覆盖电话。我已经添加了。
  • 您无法通过静态方法main 访问实例变量i。我必须是静态的。
  • Re,“我没有复制粘贴我的实际代码,”好吧,您来到这里是因为您的代码有些地方您不理解。那么你怎么能确定你没有遗漏重要的部分呢?最好的问题包含一个其他人可以实际编译和运行的代码示例,它的作用与您期望的不同。

标签: java multithreading threadpool executorservice callable


【解决方案1】:

如果我正确理解了您的问题:您可以使用 lambda 或方法引用,而这些不必显式实现 Callable。只需要遵循相同的约定:返回一些东西(不是 void,就像 Runnable 那样)并且能够抛出异常。 (不过,这只适用于 Java 8+!)

【讨论】:

  • 我想通过使用匿名内部类来提交不可调用 executorservice 的任务,就像我在案例 2 中所写的那样。但是我看到这样做与执行的任务相比,我得到了不同的输出实现可调用。我之所以这样问,是因为如果不建议通过案例 2 提交任务,那么我将要求 Task 类的实现者实现 Callable,而不是将其留给我(任务调度程序)
  • 我告诉你,你可能根本不需要匿名类: Executors.newCachedThreadPool().submit(SomeClass::doesNotImplementCallable);工作正常,只要它返回一些东西并且可以抛出异常。
  • 谢谢.. 会检查这个并接受它是否有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多