为什么线程在我的例子中表现如此?

时间:2011-11-17 18:41:09

标签: java android handler

有人可以向我解释有关线程代码的两件事,我最终几乎按照应该的方式工作。我想每隔x秒在后台执行一次周期性任务,并能够随意停止并启动它。我根据我发现的例子编码,但我不确定我是否以正确的方式制作了它。出于调试目的,该任务使用自定义showTime()显示时间。

public class LoopExampleActivity extends Activity {

    TextView Napis, Napis2;
    Button button1,button_start,button_stop;
    Handler handler = new Handler();
    Boolean tread1_running = true;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Napis = (TextView) findViewById(R.id.textView1);
        Napis2 = (TextView) findViewById(R.id.textView2);
        button1 = (Button) findViewById(R.id.button1);
        button_stop = (Button) findViewById(R.id.button_stop);
        button_start = (Button) findViewById(R.id.button_start);


        button_stop.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick (View v) {
                tread1_running = false;
                                }
            });
        button_start.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick (View v) {
                tread1_running = true;


                                }
            });

        thread.start();


    }// endof  onCreate


    final Runnable r = new Runnable()
    {
        public void run() 
        {

            handler.postDelayed(this, 1000);
            showTime(Napis2);

        }
    };

    Thread thread = new Thread()
    {
        @Override
        public void run() {
            try {
                while(tread1_running) {
                    sleep(1000);
                    handler.post(r);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };

}

现在问题是:
1)如果我用停止按钮停止它,我的线程会永远退出吗?

2)为什么我不能用start_button再次启动它?如果我在一个按钮中添加tread.start(),它会崩溃吗?

3)当我让线程运行并将一个条件放入处理程序时,我尝试了第二个版本。我能让它工作的唯一方法是通过添加

来在处理程序中循环conditionaly
if (thread1_running) {
                handler.postDelayed(this, 2000);
                showTime(Napis2);
            }

将线程中的条件更改为

 while (true) 
但是我有一个一直运行的开放线程,我在处理程序中启动并停止它,并且它发布的内容越来越多处理程序。

所以,最后我看到它的样子:

final Runnable r = new Runnable()
{
    public void run() 
    {

        if (thread1_running) handler.postDelayed(this, 1000);
            showTime(Napis2);

    }
};

Thread thread = new Thread()
{
    @Override
    public void run() {
        try {
            while(true) {
                sleep(1000);
                if (thread1_running) handler.post(r);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
};

这样做的正确方法是启动和停止整个线程吗?或者那是最好的方式?

2 个答案:

答案 0 :(得分:0)

在java中用state machine描述的线程。

当线程离开其run方法时,它进入停止状态并且无法重新启动。

你应该像通常那样通过运行方法来停止一个线程,这是正确的方法。

如果要“重新启动线程”,请启动线程类的新实例。

您应该更好地封装您的线程及其运行字段。它应该在你的线程类中,类应该提供一个公共方法来切换布尔值。没有人关心你的数据结构,隐藏它们。 :)

您应该考虑将runOnUIThread用于runnable,它比处理程序更容易使用。

答案 1 :(得分:0)

以我的拙见,实现这类目标的最佳方法是postDelayed(Runnable, long)

你可以这样做。班级定义:

private Handler mMessageHandler = new Handler();

private Runnable mUpdaterRunnable = new Runnable() {
        public void run() {
            doStuff();
            showTime(Napis2);
            mMessageHandler.postDelayed(mUpdaterRunnable, 1000);
        }
};

并像这样控制真实的跑步/停止:

开始:

mMessageHandler.postDelayed(mUpdaterRunnable, 1000);

停下来:

mMessageHandler.removeCallbacks(mUpdaterRunnable);

在我的拙见中,这简单得多了。