如果我需要从线程的runnable对象返回一个对象怎么办?

时间:2011-02-27 13:28:11

标签: java

我需要的是返回token对象作为adapter.authenticate()操作置于线程中的结果。不知道如何从那里返回一个物体,请指教。谢谢。

public Token authenticate(final String email, final String password) {

        Thread mThread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    token = adapter.authenticate(email, password); // I need token to return with authenticate() method.

                } catch (NotAuthenticatedException e) {

                }
            }
        });
        mThread.start();
    }

6 个答案:

答案 0 :(得分:5)

实施Callable界面。像运行一样对待调用方法,您可以返回令牌。

答案 1 :(得分:5)

试试这个:

public Token authenticate(final String email, final String password) {
    final Token[] tokens = new Token[1];
    Thread mThread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                tokens[0] = adapter.authenticate(email, password);
            } catch (NotAuthenticatedException e) {

            }
        }
    });
    mThread.start();
    mThread.join();
    return tokens[0];
}

说明:

  • 您无法token成为Token,因为它必须是final
  • 您需要join线程,否则authenticate可能会在线程在tokens[0]中设置令牌之前返回。

还应该注意到,通过这种方式使用线程,你没有取得多少成就。你正在做的事情只是一种昂贵的方式来调用adapter.authenticate(email, password)


如果您的目标是在等待身份验证时避免阻止UI,则解决方案需要更复杂。基本上,您需要更改您的应用程序,以便需要进行身份验证的视图元素从禁用开始(例如,它们是灰色的/忽略点击/无论如何)。您执行身份验证是一个单独的线程,如上所述,当它完成时,您可以将事件发送到UI线程。接收到该事件后,UI线程应该启用禁用的视图元素。

答案 2 :(得分:1)

为什么要在另一个线程中启动某些内容然后等待结果呢?只需直接致电adapter.authenticate()

答案 3 :(得分:1)

如果你需要在gui中进行异步操作的结果,那么你需要使用一个回调方法。你需要基本上使用2个runnables。第一个runnable在单独的线程上完成工作。当该工作完成后,结果应该传递给第二个runnable,并传递给SwingUtilities.invokeLater。第二个runnable将在下一个可用的机会在EDT线程上运行,并可以使用异步操作的结果安全地更新ui。

答案 4 :(得分:1)

如果您不希望UI冻结,您需要执行以下操作:
(来源仅供参考,有编译错误等(为简洁起见))

class Sample {
    static final Executor exec = Executors.newCachedThreadPool();
    final Adapter adapter = new Adapter();

    public Token processRequest(final Email email, final Password password){
        Future<Token> future = exec.submit(
                   new Callable<Token>(){
                       @Override
                       public Token call(){
                           return adapter.authenticate(email, password);
                       }
                   });
       //do some stuff
       if(future.isDone()){
           //Ah, it's done.
           return future.get();
       }
       //Not done yet. do some more useful stuff.

       //Nothing to do anymore. Just block on the future and 
       // wait until it's finished.
       return future.get();
    }
}

当然,您可以将未来存储在与会话关联的某个位置,并且仅在用户请求时返回等。

答案 5 :(得分:0)

您的authenticate()方法无法返回Token(除非它可以是占位符对象),因为它可以立即返回,但结果可能尚未发现。

让外部对象实现一个回调方法,比如void authenticationComplete(Token authToken),并让你的Runnable在结果到达时调用该方法。

class Authenticator {
  ...
  public void authenticate(final String email, final String password) {
     new Thread(new Runnable() {
       public void run() { 
         Authenticator.this.authenticationComplete(
           adapter.authenticate(email, password)
         );
       }
     }).start();
  }

  public void authenticationComplete(Token authToken) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        // Update your UI
      }
    });
  }
}