我正在编写一个应用程序,该应用程序必须启动,暂停和重新启动用户按下[启动和中止]按钮的线程。为了控制线程,我创建了一个服务来使用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(原生方法)
答案 0 :(得分:1)
稍微偏离主题:你为什么要手工做所有事情?你"服务"是什么意思?类?如果您希望实施Android Service
,则必须扩展Service
并将其添加到清单。
针对您的具体问题:
您的restart
方法不会重新启动Thread,它只会更改变量。您需要再次调用start
,因为它已完全停止(run
方法已完全执行,不再检查该变量)。如果需要确保只运行一个实例,则可以使用其他同步方法。
由于单个Thread
只能执行一次,您需要以太创建新的线程对象,或者实现自己的启动行为(让线程等待直到它被中断或类似)。
顺便说一句,您的变量Working
不是线程安全的。将其标记为volatile
以解决可能的同步问题。