Java 如何强制主线程等待活套结束其工作
我在安卓应用程序的Java 如何强制主线程等待活套结束其工作,java,android,multithreading,Java,Android,Multithreading,我在安卓应用程序的服务中使用Looper。通常它是工作没有任何问题。但在某些情况下(例如,当我尝试调试我的应用程序时),它会显示应用程序内部存在竞争Looper正在启动,Thread和Handler正在方法startMessageThread()中创建,该方法在Service.onCreate()方法结束时被调用 if (looperRun) { notify(); looperRun = false; } 这种竞争是因为还有其他方法和类使用在Loope
服务中使用Looper
。通常它是工作没有任何问题。但在某些情况下(例如,当我尝试调试我的应用程序时),它会显示应用程序内部存在竞争Looper
正在启动,Thread
和Handler
正在方法startMessageThread()
中创建,该方法在Service.onCreate()
方法结束时被调用
if (looperRun) {
notify();
looperRun = false;
}
这种竞争是因为还有其他方法和类使用在Looper.loop()之前初始化的这个类代码>。在某些情况下,这些方法在Looper
结束之前运行。它会导致NullPointerException
public class MyService extends Service {
private Thread thread;
private Handler handler;
@Override
public void onCreate() {
super.onCreate();
//some code
startMessageThread();
}
private void startMessageThread() {
thread = new Thread() {
@Override
public void run() {
Looper.prepare();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
//message handling
}
}
};
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
Looper.loop();
}
}
}
}
如果我是对的,这个问题与此非常相似,但我不想在创建“HandlerThread”后立即发送任何消息。只是强制主线程在onCreate
方法的末尾等待活套
结束
我已尝试在服务的末尾添加此项。onCreate
方法:
synchronized (thread) {
try {
if (looperRun) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
looperRun
当然是boolean
。我添加了looperRun=true
beforeLooper.loor()代码>方法调用。这段代码位于startMessageThread()方法的末尾
if (looperRun) {
notify();
looperRun = false;
}
在某些情况下,我会遇到以下例外情况:
java.lang.RuntimeException: Unable to create service com.myapplication.service.MyService:
java.lang.IllegalMonitorStateException: object not locked by thread before wait()
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2582)
at android.app.ActivityThread.access$1800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalMonitorStateException: object not locked by thread before wait()
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:364)
at com.myapplication.service.MyService.onCreate(MyService.java:162)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2572)
at android.app.ActivityThread.access$1800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
编辑
protected void startMessageThread() {
MessageThread messageThread = new MessageThread("messageThread");
messageThread.start();
messageHandler = new Handler(messageThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
//message handling
}
}
};
}
private class MessageThread extends HandlerThread {
public MessageThread(String name) {
super(name);
}
@Override
public void run() {
Looper.prepare();
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
Looper.loop();
}
}
编辑2
我尝试过类似的解决方案:我的代码如下。然而,我的应用程序在启动后似乎被冻结了
private class BackgroundThread extends HandlerThread {
private Handler handler;
public BackgroundThread(String name) {
super(name);
}
@Override
public void run() {
Looper.prepare();
backgroundHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
log.finest("DEAService message:" + msg.what);
switch (msg.what) {
case MSG_INIT:
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
break;
//message handling
}
}
};
Looper.loop();
};
public synchronized void waitUntilReady() {
handler = new Handler(getMainLooper());
}
}
我使用此方法启动此HandlerThread
,如前所述:
protected void startBackgroundThread() {
BackgroundThread backgroundThread = new BackgroundThread("backgroundThread");
backgroundThread.start();
backgroundThread.waitUntilReady();
backgroundHandler.sendEmptyMessage(MSG_INIT);
}
正如我上面提到的-应用程序似乎在启动后被冻结。什么也不会发生。您永远不应该阻塞主线程。从来没有
我已经使用过好几次了,没有任何问题,像这样的好用的handyHandlerThread
类:
HandlerThread ht = new HandlerThread("myThread");
ht.start();
Handler handler = new Handler(ht.getLooper());
handler.post(... stuff
也许你应该试一试
编辑:
对不起,有两种处理方法,我原来的帖子是另一种。你使用的方式是这样的
HandlerThread ht = new HandlerThread("myThread");
ht.start();
Handler handler = new Handler(ht.getLooper()){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
//message handling
}
}
};
新编辑:
请参阅代码
protected void startMessageThread() {
HandlerThread messageThread = new HandlerThread("messageThread");
messageThread.start();
messageHandler = new Handler(messageThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case INIT:
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
break;
}
}
};
messageHandler.sendEmptyMessage(INIT);
}
你永远都不应该阻塞主线程。从来没有
我已经使用过好几次了,没有任何问题,像这样的好用的handyHandlerThread
类:
HandlerThread ht = new HandlerThread("myThread");
ht.start();
Handler handler = new Handler(ht.getLooper());
handler.post(... stuff
也许你应该试一试
编辑:
对不起,有两种处理方法,我原来的帖子是另一种。你使用的方式是这样的
HandlerThread ht = new HandlerThread("myThread");
ht.start();
Handler handler = new Handler(ht.getLooper()){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
//message handling
}
}
};
新编辑:
请参阅代码
protected void startMessageThread() {
HandlerThread messageThread = new HandlerThread("messageThread");
messageThread.start();
messageHandler = new Handler(messageThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case INIT:
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
break;
}
}
};
messageHandler.sendEmptyMessage(INIT);
}
你永远都不应该阻塞主线程。从来没有
我已经使用过好几次了,没有任何问题,像这样的好用的handyHandlerThread
类:
HandlerThread ht = new HandlerThread("myThread");
ht.start();
Handler handler = new Handler(ht.getLooper());
handler.post(... stuff
也许你应该试一试
编辑:
对不起,有两种处理方法,我原来的帖子是另一种。你使用的方式是这样的
HandlerThread ht = new HandlerThread("myThread");
ht.start();
Handler handler = new Handler(ht.getLooper()){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
//message handling
}
}
};
新编辑:
请参阅代码
protected void startMessageThread() {
HandlerThread messageThread = new HandlerThread("messageThread");
messageThread.start();
messageHandler = new Handler(messageThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case INIT:
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
break;
}
}
};
messageHandler.sendEmptyMessage(INIT);
}
你永远都不应该阻塞主线程。从来没有
我已经使用过好几次了,没有任何问题,像这样的好用的handyHandlerThread
类:
HandlerThread ht = new HandlerThread("myThread");
ht.start();
Handler handler = new Handler(ht.getLooper());
handler.post(... stuff
也许你应该试一试
编辑:
对不起,有两种处理方法,我原来的帖子是另一种。你使用的方式是这样的
HandlerThread ht = new HandlerThread("myThread");
ht.start();
Handler handler = new Handler(ht.getLooper()){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
//message handling
}
}
};
新编辑:
请参阅代码
protected void startMessageThread() {
HandlerThread messageThread = new HandlerThread("messageThread");
messageThread.start();
messageHandler = new Handler(messageThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case INIT:
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
break;
}
}
};
messageHandler.sendEmptyMessage(INIT);
}
我尝试过这个代码,一切似乎都很好
private class BackgroundThread extends HandlerThread {
private Handler handler;
public BackgroundThread(String name) {
super(name);
}
@Override
public void run() {
Looper.prepare();
backgroundHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
log.finest("DEAService message:" + msg.what);
switch (msg.what) {
//message handling
}
}
};
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
Looper.loop();
};
public synchronized void waitUntilReady() {
handler = new Handler(getMainLooper());
}
}
然后用以下代码启动此HandlerThread
:
protected void startBackgroundThread() {
BackgroundThread backgroundThread = new BackgroundThread("backgroundThread");
backgroundThread.start();
backgroundThread.waitUntilReady();
}
我尝试过这个代码,一切似乎都很好
private class BackgroundThread extends HandlerThread {
private Handler handler;
public BackgroundThread(String name) {
super(name);
}
@Override
public void run() {
Looper.prepare();
backgroundHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
log.finest("DEAService message:" + msg.what);
switch (msg.what) {
//message handling
}
}
};
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
Looper.loop();
};
public synchronized void waitUntilReady() {
handler = new Handler(getMainLooper());
}
}
然后用以下代码启动此HandlerThread
:
protected void startBackgroundThread() {
BackgroundThread backgroundThread = new BackgroundThread("backgroundThread");
backgroundThread.start();
backgroundThread.waitUntilReady();
}
我尝试过这个代码,一切似乎都很好
private class BackgroundThread extends HandlerThread {
private Handler handler;
public BackgroundThread(String name) {
super(name);
}
@Override
public void run() {
Looper.prepare();
backgroundHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
log.finest("DEAService message:" + msg.what);
switch (msg.what) {
//message handling
}
}
};
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
Looper.loop();
};
public synchronized void waitUntilReady() {
handler = new Handler(getMainLooper());
}
}
然后用以下代码启动此HandlerThread
:
protected void startBackgroundThread() {
BackgroundThread backgroundThread = new BackgroundThread("backgroundThread");
backgroundThread.start();
backgroundThread.waitUntilReady();
}
我尝试过这个代码,一切似乎都很好
private class BackgroundThread extends HandlerThread {
private Handler handler;
public BackgroundThread(String name) {
super(name);
}
@Override
public void run() {
Looper.prepare();
backgroundHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
log.finest("DEAService message:" + msg.what);
switch (msg.what) {
//message handling
}
}
};
MyObject myObject = new MyObject(arg1, arg2);
myObject.init();
myObject.attr = myAttr;
Looper.loop();
};
public synchronized void waitUntilReady() {
handler = new Handler(getMainLooper());
}
}
然后用以下代码启动此HandlerThread
:
protected void startBackgroundThread() {
BackgroundThread backgroundThread = new BackgroundThread("backgroundThread");
backgroundThread.start();
backgroundThread.waitUntilReady();
}
嗯,我可以将我的线程
切换到HandlerThread
。但是我可以通过handler
以这种方式创建什么东西呢?我不能以这种方式放置在onCreate
完成后运行的任何代码。我还有一个问题:我应该以这种方式将我在问题中提到的代码放置在哪里,它位于Looper.loop()
之前的run()
方法中?如果我是对的,我可以扩展HandlerThread
并将其放置在run()
方法中。但是我是否也应该在这个run()
方法Looper.prepare()
和Looper.loop()
?我不确定我是否理解你的问题。根据我在答案上发布的内容,您必须为handler
对象保留一个引用,并调用handler.sendMessage(…)
,该调用将在switch
语句中处理。无需扩展HandlerThread
您已经在扩展处理程序了
好的,我的英语不太清晰和完美。:-)我已经更新了我的问题。我在问题的第一个版本中,在Looper.loop()
之前添加了三行代码,我还添加了我想知道的解决方案。这就是我在之前的评论中所描述的。这三行代码非常重要,所以我应该把它们放在这个线程中。我已经重新编辑了答案,这似乎是可能的。嗯,我可以将线程
切换到HandlerThread
。但是我可以通过handler
以这种方式创建什么东西呢?我不能以这种方式放置在onCreate
完成后运行的任何代码。我还有一个问题:我应该以这种方式将我在问题中提到的代码放置在哪里,它位于Looper.loop()
之前的run()
方法中?如果我是对的,我可以扩展HandlerThread
并将其放置在run()
方法中。但是我是否也应该在这个run()
方法Looper.prepare()
和Looper.loop()中放置