2011-11-17 57 views
0

有人可以向我解释2个关于线程代码的东西,我最终以它应该的方式工作。我想每隔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(); 
     } 
    } 
}; 

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

回答

0

在java中使用state machine描述线程a。

当线程退出运行方法时,它进入停止状态,无法重新启动。

您应该始终停止一个线程,将它从运行方法中解脱出来,这是实现它的正确方法。

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

你应该更好地封装你的线程和它的运行领域。它应该在你的线程类中,并且类应该提供一个公共方法来控制布尔值。没人关心你的数据结构,隐藏它们。 :)

你应该考虑使用runOnUIThread作为你的runnable,它比处理程序更容易使用。

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); 

它的要简单得多,在我的愚见。

+0

好吧,看起来合乎逻辑,我该如何在单独的步伐中运行它? –

+0

我想我需要一个单独的胎面,因为我需要在mUpdaterRunnable中调用通过网络的服务器,这可能会很慢(长达1秒),并且不想让我的应用程序变得糟糕。 –

+0

.....我刚刚测试了这个代码(没有线程),它在第一个mMessageHandler.postDelayed(mUpdaterRunnable,1000)上崩溃;我在我的应用程序onCreate()中做的。 –

相关问题