【问题标题】:How return a result of my method executed in thread?如何返回我在线程中执行的方法的结果?
【发布时间】:2015-09-15 12:32:47
【问题描述】:

我有一个返回结果的方法(返回一个整数),我的方法在线程中执行以加载 40 000 个对象,我返回一个整数来计算加载的对象数。我的问题是,如何用 Thread 返回 int ?其实是直接返回结果,等于0。

public int ajouter(params) throws DaoException, ConnectException {
    final ProgressDialog dialog = ProgressDialog.show(mActivity, "Title",
            "Message", true);
    final Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            dialog.dismiss();
        }
    };
    Thread t = new Thread() {
        public void run() {
            try {
                Str_Requete = "SELECT * FROM Mytable";
                ResultSet result = ExecuteQuery(Str_Base, Str_Requete);
                Index = addObjects(result);
                handler.sendEmptyMessage(0);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    };
    t.start();
    return Index;
}

当我在 mainActivity 中调用我的方法时:

 int test = myObjs.ajouter(params);

test等于0,直接返回值... 我的约束是没有使用 AsyncTask。

【问题讨论】:

  • 制作一个静态计数器并在你的线程run方法中更新它并返回它。
  • 看在上帝的份上,请遵循 Android 命名约定。
  • Rustam,我认为使用静态变量来容纳在另一个线程上完成的计算结果是一个可怕的建议。它不是线程安全的,您将无法并行运行多个不同的作业,并且调用代码无法知道何时计算完成。这不是静态变量的用途。

标签: java android multithreading


【解决方案1】:

使用线程的重点不是在执行线程任务时阻塞调用代码。 Thread.start() 立即返回,但同时会启动一个与当前线程并行的新线程,该线程将执行 run() 方法中的代码。

所以根据定义,不存在从线程执行中返回值这样的事情。您必须以某种方式将信号从执行任务的线程发送回您需要结果的线程。有很多方法可以做到这一点,有标准的 Java 等待/通知方法,还有 Java 并发库等。

由于这是 Android,并且我假设您的调用代码在主线程上运行,因此使用 Handler 的功能可能是明智的。事实上,你已经在这样做了——你有一个处理程序,当线程完成它的工作时关闭对话框——但出于某种原因,你似乎期望该工作的结果在它开始之前就准备好了。使用一些对计算值执行某些操作的代码来扩展您现有的 Handler 并删除在另一个线程计算变量之前或同时返回变量值的代码是合理的。

我也强烈建议您学习一些并发教程,例如 Oracle's concurrency lessonAndroid Thread guidelines,以真正了解后台发生的情况。在不掌握概念的情况下编写并发代码迟早会失败,因为并发的本质是多件事同时发生,会以随机顺序完成等等。它可能不会经常失败,但你会发疯想知道为什么 90% 的时间都有效的东西突然失败了。这就是为什么原子性、线程同步等主题对于理解至关重要的原因。

编辑:启动工作线程、执行一些工作、将事件发回主线程的简单 Android 示例。

public class MyActivity extends Activity {
    private Handler mHandler = new Handler();

    ...

    private void doSomeWorkInBackground() {
        new Thread() {
            public void run() {
                // do slow work, this may be blocking
                mHandler.post(new Runnable() {
                    public void run() {
                        // this code will run on main thread, 
                        // updating your UI or whatever you need. 
                        // Hence, code here must NOT be blocking.
                    }
                });
            }
        }.start();

        // This code will be executed immediately on the main thread, and main thread will not be blocked
    }

在这个例子中你也可以使用Activity.runOnUiThread(Runnable)。 但是请考虑AsyncTask 基本上以非常方便的方式包装了这种功能,所以如果它适合您的目的,您应该考虑使用AsyncTask

【讨论】:

  • 如果我理解,我必须在我的处理程序中返回我的值?
  • 我找到了解决方案的一部分,我使用带有 Callable 和 Future 的框架 Executor 但我有一个问题,当我在 Future 任务上调用 .get 时,UI 线程被阻塞,知道解决方案?
  • Future.get() 应该阻塞,除非工作已经完成,请参阅docs.oracle.com/javase/7/docs/api/java/util/concurrent/…。在 Android 中,主线程使用事件循环并且永远不要挂起,即永远不要调用任何阻塞方法。相反,您的线程应该使用 Handler.post(Runnable) 或类似技术将事件发布到主线程。在您的特定情况下,我不太确定 Future 和 Callable 是否真的增加了任何附加值。我将用一个简单的例子来更新我的答案 start worker -> perform work -> post back。
【解决方案2】:

如果您不想使用 AsyncTask 或 ForkJoin,那么您可以实现一个接口,例如在你的主类中回调。

在您的示例中,您不必等到线程完成... thread.join

一个解决方案: 您的 Thread 是一个额外的类,带有一个构造函数来保存对调用类的引用。

public Interface callback
{
public int done();
}


public class main implements callback
{
...

CustomThread t = new CustomThread(this)

...
}


public class CustomThread extends Thread
{

    private Callback cb;

    public CustomThread(Callback cb)
    {
        this.cb=cb;
    }
    .
    .
    .
    //when done
    cb.done(int)
 }

【讨论】:

  • 不确定这是一个很好的解决方案。请注意,这只允许在完成工作的线程中调用回调方法。通常,您希望将结果发送回请求将工作卸载到工作线程的线程。特别是在 Android 中,OP 很可能想要对结果做一些事情,例如更新某种 UI,即使您当然可以从回调实现中调用处理程序或 runOnUiThread 调用,我真的没有看到任何添加在匿名线程类或 AsyncTask 上使用您的方案的值。
  • 我同意你的观点,我的方案不比 AsyncTask 更有价值。 Normaly 我会使用 Java concurreny / forkjoin。也许我误解了这个问题:如何在不使用 asynctask 的情况下返回 thread.execute 的值。我想展示一个可能的替代方案。
猜你喜欢
  • 1970-01-01
  • 2016-04-26
  • 2019-05-08
  • 1970-01-01
  • 2019-08-18
  • 2014-03-09
  • 2013-01-23
  • 1970-01-01
  • 2021-05-16
相关资源
最近更新 更多