Android:暂停并重新启动一个线程,使用flags vs .wait()和.notify()

时间:2013-09-02 00:12:28

标签: android multithreading wait notify

我正在编写一个应用程序,该应用程序必须启动,暂停和重新启动用户按下[启动和中止]按钮的线程。为了控制线程,我创建了一个服务来使用Activity,如下所示:

活动代码

public class SoundLocalizer extends Activity {

 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(D) Log.e(TAG, " ON CREATE ");

        // Set up the window layout
        setContentView(R.layout.main);

    }

     public void onStart() {
        super.onStart();
        if(D) Log.e(TAG, "++ ON START ++");

        mHelloService = new HelloMessage(ThisContext, mHandler, LocalIP);
        mHelloService.start();

        setup();
    }


    public void onReStart(){

        mHelloService.restart();
    }

    public void onWait(){

        mHelloService.stop();

        if(D) Log.e(TAG, "-- ON WAIT --");
    }

    private void setupChat() {
        Log.d(TAG, "setupChat()");


        mStartButton = (Button) findViewById(R.id.btnStart);
        mStartButton.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {

                //The aplicacion have already been lauched
                if(Begin){

                    onReStart();
                }
                isRecording = true;
                enableButtons(false);



            }
        });

        mAbortButton = (Button) findViewById(R.id.btnAbort);
        mAbortButton.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {

                enableButtons(true);

                Loop=false;
                isRecording=false;
                WaitForMaster=false;
                onWait();   
                Begin=true;


            }
        });

}



}

服务守则

public class HelloMessage {

    Context mContext ;
    private final Handler mHandler;     
    private boolean Working=true;


    public HelloMessage(Context context, Handler handler, String IP){

        mContext=context;
        mHandler = handler;
        Local_IP_String=IP;
        String[] IP_Parts = IP.split("\\.");
        LocalIP=Integer.parseInt(IP_Parts[3]);

     }

     public void restart() {        

     Working=true;               

    /*
    mHelloThread.notify();
    */

 }


 public synchronized void start() {

    Working=true;                
    mHelloThread = new HelloThread();
     mHelloThread.start();

     }


public void stop() {

    Working=false;

            /*
    try {
        mHelloThread.wait();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

     */

    }

public class HelloThread extends Thread {

     DatagramSocket mSocket ;
     InetAddress myBcastIP;  

        public HelloThread() {

            try { 

                       //Here I initialize some variables

             } catch (IOException e) { 

                 ...
             }

        }

        public void run(){

            //Listen on socket to receive messages 
            try{                

                        while(Working){                 

                                  //Do things

                            }

                        }


             } catch (IOException e) { 

                      ...

             }


}

问题:当我按下Abort时,活动正确调用: mHelloService.stop(),并且标志 Working 变为 false ,并且" while循环"在服务的线程停止工作。

直到这一点,一切都很完美。但后来我想重新启动调用方法 mHelloService.restart()的循环,它应该使工作成为 true ,但该线程没有&#39 ;重新开始。我做错了什么?

------------其他版本我也试过更糟糕的结果---------------

mHelloService.stop()中使用mHelloThread.wait(),在 mHelloService.restart()中使用mHelloThread.notify()

我在LogCat中得到了这个:

  

09-02 02:08:54.640:D / AndroidRuntime(17463):关闭VM 09-02   02:08:54.640:W / dalvikvm(17463):threadid = 1:线程退出   未捕获的异常(组= 0x413eb300)09-02 02:08:54.648:   E / AndroidRuntime(17463):FATAL EXCEPTION:main 09-02 02:08:54.648:   E / AndroidRuntime(17463):java.lang.IllegalMonitorStateException:   对象()之前没有被线程锁定的对象()09-02 02:08:54.648:   E / AndroidRuntime(17463):at java.lang.Object.wait(Native Method)   09-02 02:08:54.648:E / AndroidRuntime(17463):at   java.lang.Object.wait(Object.java:364)09-02 02:08:54.648:   E / AndroidRuntime(17463):at   android.nacho.SoundLocalizer.HelloMessage.stop(HelloMessage.java:88)   09-02 02:08:54.648:E / AndroidRuntime(17463):at   android.nacho.SoundLocalizer.SoundLocalizer.onWait(SoundLocalizer.java:367)   09-02 02:08:54.648:E / AndroidRuntime(17463):at   android.nacho.SoundLocalizer.SoundLocalizer $ 3.onClick(SoundLocalizer.java:441)   09-02 02:08:54.648:E / AndroidRuntime(17463):at   android.view.View.performClick(View.java:4084)09-02 02:08:54.648:   E / AndroidRuntime(17463):at   android.view.View $ PerformClick.run(View.java:16966)09-02   02:08:54.648:E / AndroidRuntime(17463):at   android.os.Handler.handleCallback(Handler.java:615)09-02   02:08:54.648:E / AndroidRuntime(17463):at   android.os.Handler.dispatchMessage(Handler.java:92)09-02   02:08:54.648:E / AndroidRuntime(17463):at   android.os.Looper.loop(Looper.java:137)09-02 02:08:54.648:   E / AndroidRuntime(17463):at   android.app.ActivityThread.main(ActivityThread.java:4745)09-02   02:08:54.648:E / AndroidRuntime(17463):at   java.lang.reflect.Method.invokeNative(Native Method)09-02   02:08:54.648:E / AndroidRuntime(17463):at   java.lang.reflect.Method.invoke(Method.java:511)09-02 02:08:54.648:   E / AndroidRuntime(17463):at   com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:786)   09-02 02:08:54.648:E / AndroidRuntime(17463):at   com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)09-02   02:08:54.648:E / AndroidRuntime(17463):at   dalvik.system.NativeStart.main(原生方法)

非常感谢你的时间


注1:

如果我在restart()中添加mHelloThread.start(),我会在LogCat中得到这个:

  

09-02 03:05:07.664:D / AndroidRuntime(17657):关闭VM 09-02   03:05:07.664:W / dalvikvm(17657):threadid = 1:线程退出   未捕获的异常(组= 0x413eb300)09-02 03:05:07.672:   E / AndroidRuntime(17657):FATAL EXCEPTION:main 09-02 03:05:07.672:   E / AndroidRuntime(17657):java.lang.IllegalThreadStateException:Thread   已经开始了。 09-02 03:05:07.672:E / AndroidRuntime(17657):at   java.lang.Thread.start(Thread.java:1045)09-02 03:05:07.672:   E / AndroidRuntime(17657):at   android.nacho.SoundLocalizer.HelloMessage.restart(HelloMessage.java:67)   09-02 03:05:07.672:E / AndroidRuntime(17657):at   android.nacho.SoundLocalizer.SoundLocalizer.onReStart(SoundLocalizer.java:353)   09-02 03:05:07.672:E / AndroidRuntime(17657):at   android.nacho.SoundLocalizer.SoundLocalizer $ 2.onClick(SoundLocalizer.java:421)   09-02 03:05:07.672:E / AndroidRuntime(17657):at   android.view.View.performClick(View.java:4084)09-02 03:05:07.672:   E / AndroidRuntime(17657):at   android.view.View $ PerformClick.run(View.java:16966)09-02   03:05:07.672:E / AndroidRuntime(17657):at   android.os.Handler.handleCallback(Handler.java:615)09-02   03:05:07.672:E / AndroidRuntime(17657):at   android.os.Handler.dispatchMessage(Handler.java:92)09-02   03:05:07.672:E / AndroidRuntime(17657):at   android.os.Looper.loop(Looper.java:137)09-02 03:05:07.672:   E / AndroidRuntime(17657):at   android.app.ActivityThread.main(ActivityThread.java:4745)09-02   03:05:07.672:E / AndroidRuntime(17657):at   java.lang.reflect.Method.invokeNative(Native Method)09-02   03:05:07.672:E / AndroidRuntime(17657):at   java.lang.reflect.Method.invoke(Method.java:511)09-02 03:05:07.672:   E / AndroidRuntime(17657):at   com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:786)   09-02 03:05:07.672:E / AndroidRuntime(17657):at   com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)09-02   03:05:07.672:E / AndroidRuntime(17657):at   dalvik.system.NativeStart.main(原生方法)

1 个答案:

答案 0 :(得分:1)

稍微偏离主题:你为什么要手工做所有事情?你"服务"是什么意思?类?如果您希望实施Android Service,则必须扩展Service并将其添加到清单。


针对您的具体问题: 您的restart方法不会重新启动Thread,它只会更改变量。您需要再次调用start,因为它已完全停止(run方法已完全执行,不再检查该变量)。如果需要确保只运行一个实例,则可以使用其他同步方法。

由于单个Thread只能执行一次,您需要以太创建新的线程对象,或者实现自己的启动行为(让线程等待直到它被中断或类似)。

顺便说一句,您的变量Working不是线程安全的。将其标记为volatile以解决可能的同步问题。