多次启动/调用相同的线程Java Android

时间:2014-01-26 04:44:17

标签: java android multithreading

我需要在我的应用中多次调用同一个线程。使用我的原始代码,第一次可以执行得很好。但第二次崩溃 - 然后我才知道每个线程只能执行不超过一次。

我的原始代码:

View.OnClickListener myClickListener = new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        mythread.start();
    }
};


Thread mythread = new Thread(){

    @Override
    public void run() {

        runOnUiThread(new Runnable() {
            public void run() {
                demoBt.setText("Running...");
            }
        });

     try {
        sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }       

        runOnUiThread(new Runnable() {
            public void run() {
                demoBt.setText("Finished...");
            }
        });
    }
};

正如我所说,如果我第二次尝试运行它会崩溃。所以我尝试修改它:

View.OnClickListener myClickListener = new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        test();
    }
};

private void test(){

    Thread mythread = new Thread(){

        @Override
        public void run() {

            runOnUiThread(new Runnable() {
                public void run() {
                    demoBt.setText("Running...");
                }
            });

         try {
            sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }       

            runOnUiThread(new Runnable() {
                public void run() {
                    demoBt.setText("Finished...");
                }
            });
        }
    };

    mythread.start();
}

效果很好;但我的问题是,这是否是执行此操作的正确方法,还是有更优化的方法来执行此操作?

另外,从另一个线程的内部调用线程是否可以接受? (就像我把东西放在我的新线程中的UI Thread上的方式)

编辑: 这只是一个例子。对于我的实际代码,我需要进行大量基于数学的模拟,需要10秒才能完成。根据将向用户显示的结果,他们可能希望更改其输入参数并让模拟再次运行。这将发生好几次。

4 个答案:

答案 0 :(得分:4)

除了使用AsyncTask或runOnUiThread()的其他好答案之外,您还可以将私有成员定义为Runnable,如下所示:

private Runnable mytask = new Runnable() {
    @Override
    public void run() {

        runOnUiThread(new Runnable() {
            public void run() {
                demoBt.setText("Running...");
            }
        });

     try {
        sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }       

        runOnUiThread(new Runnable() {
            public void run() {
                demoBt.setText("Finished...");
            }
        });
    }
};

然后,无论何时想要运行它,都要执行

new Thread(mytask).start();

答案 1 :(得分:2)

没有什么不好,但我认为更好的方法是使用AsyncTask。它完全是为这种情况而设计的。

您可以多次使用AsyncTask,只需创建一个新的new MyAsyncTask().execute(""); {来自here

答案 2 :(得分:0)

  

另外,从另一个线程的内部调用线程是否可以接受? (就像我把东西放在我的新线程中的UI Thread上的方式)

runOnUiThread仅用于此目的。但通常有更好的方法(例如AsyncTask),所以使用这种方法可能是一个坏主意。

  

我的问题是,这是否是执行此操作的正确方法,还是有更优化的方法来执行此操作?

您不应仅仅使用线程来安排未来的任务。它们对于与主线程并行执行某些操作非常有用,但会增加许多潜在的错误(尝试在它之间旋转屏幕打印running..finished,可能会崩溃)

我会在你的情况下使用CountDownTimer

Handler例如在这里:Schedule task in android

答案 3 :(得分:0)

从提供的代码中我假设您想要在长时间的数学计算之前和之后执行UI操作。在诸如@Andres建议的情况下,AsyncTask是您的最佳选择。它提供onPreExecute方法,onPostExecute,它在UI线程上运行,因此不需要显式调用runOnUiThread。

关键概念:

  1. 您无法启动已启动的主题。这将返回IllegalStateException。如果需要再次执行相同的任务,则应创建一个新实例。

  2. 如果您发现自己创建了多个线程实例(甚至是AsyncTask),因为您需要反复运行相同的任务,我建议您使用线程池或简单的Java Executor服务。创建一个singleThread或者可以是pool并将你的runnable发布到executorService上,它将负责其余部分。

  3. 线程间或进程间通信是非常常见的要求。