0

我正在编写一个应用程序,该应用程序必须根据用户按下的按钮来启动、暂停和重新启动线程 [Start and Abort]。为了控制线程,我创建了一个服务来使用 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()方法,这应该使Working变为true,但线程不会再次启动。我究竟做错了什么?

------------ 其他版本我也试过了,结果更差 ---------------

在 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: 线程退出未捕获异常 (group=0x413eb300) 09 -02 02:08:54.648: E/AndroidRuntime(17463): 致命异常: main 09-02 02:08:54.648: E/AndroidRuntime(17463): java.lang.IllegalMonitorStateException: 在wait()之前对象没有被线程锁定09-02 02:08:54.648: E/AndroidRuntime(17463): 在 java.lang.Object.wait(Native Method) 09-02 02:08:54.648: E/AndroidRuntime(17463): 在 java.lang.Object .wait(Object.java:364) 09-02 02:08:54.648: E/AndroidRuntime(17463): 在 android.nacho.SoundLocalizer.HelloMessage.stop(HelloMessage.java:88) 09-02 02:08:54.648 : E/AndroidRuntime(17463): 在 android.nacho.SoundLocalizer.SoundLocalizer.onWait(SoundLocalizer.java:367) 09-02 02:08:54.648: E/AndroidRuntime(17463):在 android.nacho.SoundLocalizer.SoundLocalizer$3.onClick(SoundLocalizer.java:441) 09-02 02:08:54.648: E/AndroidRuntime(17463): 在 android.view.View.performClick(View.java:4084) 09 -02 02:08:54.648: E/AndroidRuntime(17463): 在 android.view.View$PerformClick.run(View.java:16966) 09-02 02:08:54.648: E/AndroidRuntime(17463): 在 android .os.Handler.handleCallback(Handler.java:615) 09-02 02:08:54.648: E/AndroidRuntime(17463): 在 android.os.Handler.dispatchMessage(Handler.java:92) 09-02 02:08 :54.648: E/AndroidRuntime(17463): 在 android.os.Looper.loop(Looper.java:137) 09-02 02:08:54.648: E/AndroidRuntime(17463): 在 android.app.ActivityThread.main( ActivityThread.java:4745) 09-02 02:08:54.648: E/AndroidRuntime(17463): 在 java.lang.reflect.Method.invokeNative(Native Method) 09-02 02:08:54.648:E/AndroidRuntime(17463): 在 java.lang.reflect.Method.invoke(Method.java:511) 09-02 02:08:54.648: E/AndroidRuntime(17463): 在 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):在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: 线程退出未捕获异常 (group=0x413eb300) 09 -02 03:05:07.672: E/AndroidRuntime(17657): 致命异常: main 09-02 03:05:07.672: E/AndroidRuntime(17657): java.lang.IllegalThreadStateException: 线程已经启动。09-02 03:05:07.672: E/AndroidRuntime(17657): 在 java.lang.Thread.start(Thread.java:1045) 09-02 03:05:07.672: E/AndroidRuntime(17657): 在 android。 nacho.SoundLocalizer.HelloMessage.restart(HelloMessage.java:67) 09-02 03:05:07.672: E/AndroidRuntime(17657): 在 android.nacho.SoundLocalizer.SoundLocalizer.onReStart(SoundLocalizer.java:353) 09-02 03:05:07.672: E/AndroidRuntime(17657): 在 android.nacho.SoundLocalizer.SoundLocalizer$2.onClick(SoundLocalizer.java:421) 09-02 03:05:07。

4

1 回答 1

1

有点题外话:你为什么要手动做所有事情?您的“服务”类是什么意思?如果你想实现一个 Android Service,你必须扩展Service它并将其添加到清单中。


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

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

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

于 2013-09-02T00:24:18.837 回答