【问题标题】:Returning a value from Runnable从 Runnable 返回一个值
【发布时间】:2012-11-20 23:46:35
【问题描述】:

Runnablerun 方法的返回类型为void,不能返回值。但是我想知道是否有任何解决方法。

我有这样的方法:

public class Endpoint {
    public method() {
       Runnable runcls = new RunnableClass();
       runcls.run()
    }
}

run的方法是这样的:

public class RunnableClass implements Runnable {
    
    public JaxbResponse response;

    public void run() {
        int id = inputProxy.input(chain);
        response = outputProxy.input();
    }
}

我想访问method 中的response 变量。这可能吗?

【问题讨论】:

  • response 是从哪里来的?或者更好的是outputProxy ?
  • 这些方法在不同的类中,我应该编辑我的问题,很抱歉让你感到困惑。

标签: java runnable


【解决方案1】:

看看Callable 类。这通常通过executor service提交

它可以返回一个future对象,该对象在线程完成时返回

【讨论】:

    【解决方案2】:

    使用Callable<V> 而不是使用Runnable 接口。

    例子:

    public static void main(String args[]) throws Exception {
        ExecutorService pool = Executors.newFixedThreadPool(3);
        Set<Future<Integer>> set = new HashSet<>();
    
        for (String word : args) {
          Callable<Integer> callable = new WordLengthCallable(word);
          Future<Integer> future = pool.submit(callable);
          set.add(future);
        }
    
        int sum = 0;
        for (Future<Integer> future : set) {
          sum += future.get();
        }
    
        System.out.printf("The sum of lengths is %s%n", sum);
        System.exit(sum);
    }
    

    在本例中,您还需要实现类WordLengthCallable,它实现了Callable 接口。

    【讨论】:

    • Exception in thread "main" java.lang.Error: Unresolved compilation problem: WordLengthCallable cannot be resolved to a type。我不够聪明,无法修复它,但它对我不起作用。
    • 另外我认为new HashSet&lt;Future,Integer&gt;&gt;() 应该是new HashSet&lt;Future&lt;Integer&gt;&gt;()
    • @localhost 它只是 Callable Interface 的具体实现。有关 Callable 的更多信息:blogs.oracle.com/CoreJavaTechTips/entry/get_netbeans_6
    • 如果你的委托没有抛出任何异常,最好使用Supplier&lt;T&gt;
    【解决方案3】:

    看看callable interface,也许这符合您的需求。您还可以尝试通过在 run() 方法中调用 setter-method 来获取响应字段的值

    public void run() {
        int id;
        id =inputProxy.input(chain);
        response = outputProxy.input();
        OuterClass.setResponseData(response);
    
    }
    

    【讨论】:

      【解决方案4】:

      如果您向RunnableClass 添加一个字段,您可以在run 中设置它并在method_ 中读取它。但是,Runnable 是一个糟糕的(Java 关键字)interface,因为它没有告诉您任何有关(概念)接口的信息(API 文档中唯一有用的行:“方法 run 的一般约定是它可以采取任何行动。”)。最好使用更有意义的接口(可能会返回一些东西)。

      【讨论】:

      • 你能提供有意义的接口的例子吗?
      • 看看OnClickHandler
      【解决方案5】:
      public void check() {
          ExecutorService executor = Executors.newSingleThreadExecutor();
          Future<Integer> result = executor.submit(new Callable<Integer>() {
              public Integer call() throws Exception {
                  return 10;
              }
          });
      
          try {
              int returnValue = result.get();
          } catch (Exception exception) {
             //handle exception
          }
      }
      

      【讨论】:

        【解决方案6】:

        一种方法是,我们必须使用Future - Callable 方法。

        另一种方式是,可以不返回值,而是保存在对象中

        例子:

        class MainThread {
            public void startMyThread() {
                Object requiredObject = new Object(); //Map/List/OwnClass
                Thread myThread = new Thread(new RunnableObject(requiredObject)).start();
                myThread.join();
        
                System.out.println(requiredObject.getRequiredValue());    
            }
        }
        
        
        
        class RunnableObject implements Runnable {
            private Object requiredObject;
        
            public RunnableObject(Object requiredObject) {
                this.requiredObject = requiredObject;
            }
        
            public void run() {
                requiredObject.setRequiredValue(xxxxx);
            }
        }
        

        因为对象作用域在同一个作用域中,所以你可以将对象传递给线程并可以在主作用域中检索。但是,最重要的是,我们必须使用 join() 方法。因为主作用域应该等待线程完成其任务。

        对于多线程情况,您可以使用List/Map 来保存线程中的值。

        【讨论】:

        • requiredObject.setRequiredValue() 不是Object 中的方法。需要一种更复杂的方法来做试图做的事情:requiredObject = result; & Object getResult() { return requiredObject; }。同样开始一个新的线程与原来的问题无关,也没有答案的必要。顺便说一句:使用由 Narendra Pathai 回答的 Callable 绝对是更好的方法。
        • 这里,Object 是 Map/List/OwnClass 已经在评论中提到过。我也清楚地提到使用成员名称。 ** required object / required value.** 如果是自定义类,我们可以编写setter和getter方法。
        【解决方案7】:

        是的,有解决方法。只需使用队列并将您想要返回的值放入其中。并从另一个线程中获取这个值。

        public class RunnableClass implements Runnable{
        
                private final BlockingQueue<jaxbResponse> queue;
        
        
                public RunnableClass(BlockingQueue<jaxbResponse> queue) {
                    this.queue = queue;
                }
        
                public void run() {
                    int id;
                    id =inputProxy.input(chain);
                    queue.put(outputProxy.input());
                }
            }
        
        
            public class Endpoint{
                public method_(){
                    BlockingQueue<jaxbResponse> queue = new LinkedBlockingQueue<>();
        
                    RunnableClass runcls = new RunnableClass(queue);
                    runcls.run()
        
                    jaxbResponse response = queue.take(); // waits until takes value from queue
                }
            }
        

        【讨论】:

        • 非常好,让我摆脱了该方法只接受 Runnable 的问题。谢谢。
        【解决方案8】:

        试试下面的

        public abstract class ReturnRunnable<T> implements Runnable {
        
            public abstract T runForResult();
        
            @Override
            public void run() {
                runForResult();
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-07-29
          • 2018-07-31
          • 2014-10-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多