问题描述
试图创建2后台线程,以及thread0发送消息到线程1,其中它
通过使用MessageHandler的处理的的机器人的活套和线程1相关的队列。消息
我期望看到线程0,1和主线程独立的线程ID。不过,我很惊讶地看到意想不到的事情。
14 09-08:23:21.089:D / MQ(4514):系统启动!今天是:2014年9月8日下午2点23分21秒
09-08 14:23:21.099:V / MQ(4514):onStartCommand()。我内部的主服务线程ID = 1
09-08 14:23:21.099:V / MQ(4514):BackgroundThread0。线程ID = 280发送消息0
09-08 14:23:21.099:V / MQ(4514):关于线程线程ID = 1收到的消息0的MessageHandler
为什么BackgroundThread1具有相同的线程ID为主要服务线程ID = 1?
我使用运行方式的Eclipse安装它,我开始它在Windows控制台窗口:
D:\\>亚行外壳上午startservice --user 0 -a -n android.intent.action.MAINcom.sandbox.mq/.MainService
启动服务:意向{行动= android.intent.action.MAIN CMP = com.sandbox.mq / .MainService}
-
包com.sandbox.mq;
公共类StartMainService扩展应用{
最终静态字符串标记=MQ; 公共无效的onCreate(){
super.onCreate();
上下文的背景下= getApplicationContext();
Log.d(TAG,系统启动今天是:+ DateFormat.getDateTimeInstance()格式(新的Date()));
}
}
-
公共类MainService延伸服务{
最终静态字符串标记=MQ;
BackgroundThread0 bthread0;
BackgroundThread1 bthread1; 公共类MqBinder扩展粘结剂{
公共MqBinder(上下文ctxt){
Log.v(TAGMqBinder()+线程ID =
+ Thread.currentThread()的getId());
}
} @覆盖
公众的IBinder onBind(意向为arg0){
返回新MqBinder(本);
}@覆盖
公众诠释onStartCommand(意向意图,诠释标志诠释startId){
Log.v(TAGonStartCommand()。我内部的主服务
+线程ID =+ Thread.currentThread()的getId());
bthread1 =新BackgroundThread1();
如果(!bthread1.isAlive()){
bthread1.start();
}其他{
Log.v(TAG。onStartCommand()bthread1已经启动);
}
bthread0 =新BackgroundThread0();
如果(!bthread0.isAlive()){
bthread0.start();
}其他{
Log.v(TAG。onStartCommand()bthread0已经启动);
}
返回START_STICKY;
} 私有类BackgroundThread0继承Thread {
处理器b1Handler; @覆盖
公共无效的run(){
super.run();
b1Handler = bthread1.b1Handler;
消息味精= b1Handler.obtainMessage(MessageHandler.TYPE0);
b1Handler.sendMessage(MSG);
Log.v(TAGBackgroundThread0。+线程ID =
+ Thread.currentThread()。的getId()+发送消息
+ msg.what);
} } 私有类BackgroundThread1继承Thread {
公共BackgroundThread1(){
超();
b1Handler =新的MessageHandler();
} 处理器b1Handler; @覆盖
公共无效的run(){
super.run();
尺蠖prepare()。
Looper.loop();
} } 私有静态类的MessageHandler扩展了Handler {
静态最终诠释键入0 = 0;
静态最终诠释TYPE1 = 1;
静态最终诠释TYPE2 = 2; 公共的MessageHandler(){ } @覆盖
公共无效的handleMessage(消息MSG){
Log.v(TAG,+上线的MessageHandler,线程ID =
+ Thread.currentThread()。的getId()+收到的消息
+ msg.what); 开关(msg.what){
案件类型0:
打破;
案例TYPE1:
打破;
案例TYPE2:
打破;
}
super.handleMessage(MSG);
}
}
}
-
<清单的xmlns:机器人=http://schemas.android.com/apk/res/android
包=com.sandbox.mq> <使用许可权的android:NAME =android.permission.SYSTEM_ALERT_WINDOW/> <用途-SDK
安卓的minSdkVersion =19
机器人:targetSdkVersion =19/> <应用
机器人:名字=com.sandbox.mq.StartMainService
机器人:allowBackup =真
机器人:图标=@绘制/ ic_launcher
机器人:标签=@字符串/ APP_NAME
机器人:执着=真
机器人:主题=@风格/ AppTheme>
<服务机器人:名字=com.sandbox.mq.MainService机器人:出口=真正的>
&所述;意图滤光器>
<作用机器人:名字=android.intent.action.MAIN/>
<类机器人:名字=android.intent.category.LAUNCHER/>
&所述; /意图滤光器>
< /服务>
< /用途>< /清单>
在Eclipse中, DDMS 窗口
1 4514原住民0 2主
* 2 4518 VmWait 0 0 GC
* 3 4519 VmWait 0 0信号的守望者
* 4 4520 Runnable接口0 2 JDWP
* 5 4521 VmWait 0 0编译
* 6 4522等待0 0 ReferenceQueueDaemon
* 7 4523等待0 0 FinalizerDaemon
* 8 4524等待0 0 FinalizerWatchdogDaemon
9 4525原住民0 0 Binder_1
10 4526母语0 0 Binder_2
11 4527母语0 0主题-279
低于以下TacBoss建议后,我得到线程ID = 450,预计。线程ID 451可能完成。
1 11756本机1主
* 2 11760 VmWait 0 0 GC
* 3 11761 VmWait 0 0信号的守望者
* 4 11762 Runnable接口0 0 JDWP
* 5 11763 VmWait 0 0编译
* 6 11764等待0 0 ReferenceQueueDaemon
* 7 11765等待0 0 FinalizerDaemon
* 8等待11766 0 FinalizerWatchdogDaemon
9 11767原住民0 0 Binder_1
10 11768本地0 0 Binder_2
11 11770本地0 0主题-450
09-08 15:06:05.089:D / MQ(7931):系统启动!今天是:2014年9月8日下午3时06分05秒
09-08 15:06:05.089:V / MQ(7931):onStartCommand()。我内部的主服务线程ID = 1
09-08 15:06:06.149:D / MQ(7946):系统启动!今天是:2014年9月8日下午3时06分06秒
09-08 15:06:06.149:V / MQ(7946):onStartCommand()。我内部的主服务线程ID = 1
09-08 15:06:10.269:D / MQ(7964):系统启动!今天是:2014年9月8日下午3时06分10秒
09-08 15:06:10.269:V / MQ(7964):onStartCommand()。我内部的主服务线程ID = 1
09-08 15:06:26.339:D / MQ(8110):系统启动!今天是:2014年9月8日下午3时06分26秒
09-08 15:06:26.339:V / MQ(8110):onStartCommand()。我内部的主服务线程ID = 1
09-08 15:06:36.319:D / MQ(8166):系统启动!今天是:2014年9月8日下午3时06分36秒
09-08 15:06:36.319:V / MQ(8166):onStartCommand()。我内部的主服务线程ID = 1
09-08 15:06:37.389:D / MQ(8182):系统启动!今天是:2014年9月8日下午3时06分37秒
09-08 15:06:37.389:V / MQ(8182):onStartCommand()。我内部的主服务线程ID = 1
09-08 15:06:41.469:D / MQ(8200):系统启动!今天是:2014年9月8日下午3时06分41秒
09-08 15:06:41.469:V / MQ(8200):onStartCommand()。我内部的主服务线程ID = 1
09-08 15:08:27.439:D / MQ(8577):系统启动!今天是:2014年9月8日下午3时08分27秒
09-08 15:08:27.439:V / MQ(8577):onStartCommand()。我内部的主服务线程ID = 1
09-08 15:08:28.479:D / MQ(8593):系统启动!今天是:2014年9月8日下午3时08分28秒
09-08 15:08:28.489:V / MQ(8593):onStartCommand()。我内部的主服务线程ID = 1
09-08 15:08:32.579:D / MQ(8612):系统启动!今天是:2014年9月8日下午3时08分32秒
09-08 15:08:32.579:V / MQ(8612):onStartCommand()。我内部的主服务线程ID = 1
09-08 15:08:48.679:D / MQ(8630):系统启动!今天是:2014年9月8日下午3时08分48秒
09-08 15:08:48.679:V / MQ(8630):onStartCommand()。我内部的主服务线程ID = 1
09-08 15:29:00.949:D / MQ(11756):系统启动!今天是:2014年9月8日下午3点29分零零秒
09-08 15:29:00.949:V / MQ(11756):onStartCommand()。我内部的主服务线程ID = 1
09-08 15:29:00.959:V / MQ(11756):BackgroundThread0。线程ID = 451发送消息0
09-08 15:29:00.959:V / MQ(11756):对线程线程ID = 450收到的消息0的MessageHandler
- code更改
私有类BackgroundThread1继承Thread {
公共BackgroundThread1(){
超();
开始();
} 处理器b1Handler; @覆盖
公共无效的run(){
super.run();
尺蠖prepare()。
活套活套= Looper.myLooper();
b1Handler =新的MessageHandler(活套);
Looper.loop();
} } 公众诠释onStartCommand(意向意图,诠释标志诠释startId){
Log.v(TAGonStartCommand()。我内部的主服务
+线程ID =+ Thread.currentThread()的getId());
bthread1 =新BackgroundThread1();
//如果(!bthread1.isAlive()){
// bthread1.start();
//}其他{
// Log.v(TAGonStartCommand()bthread1已经启动。);
//}
bthread0 =新BackgroundThread0();
如果(!bthread0.isAlive()){
bthread0.start();
}其他{
Log.v(TAG。onStartCommand()bthread0已经启动);
}
返回START_STICKY;
}
OK,这并没有弹出直线上升...
问题是你的BGThread1的构造,这code从主线程调用中创建的处理程序!这就是为什么该处理队列也连接到主线程
公共BackgroundThread1(){
超();
b1Handler =新的MessageHandler(); //这是这里的主线程...
}
如果您希望此处理另一个线程上运行,你首先要做的是这样的:
私有类BackgroundThread1扩展HandlerThread {
公共BackgroundThread1(){
超();
...
有些code
...
开始();
b1Handler =新的MessageHandler(getLooper());
//这是这里的主线程...但你创建的处理程序与新线的活套!
}
...
}
这会造成在上下文中的线程,你指望它。
=============================================== ====
延伸出的常规线程的一个例子:
类MyThread的
继承Thread { 私人处理程序将myHandler; 公共MyThread的(){
开始();
} @覆盖
公共无效的run(){
尺蠖prepare()。
活套活套= Looper.myLooper();
将myHandler =新的处理程序(活套);
Looper.loop();
}
}
现在的处理程序上的新线程上运行。
Trying to create 2 background threads and sending a message from thread0 to thread1 where it is handled by MessageHandler using the android Looper and message queue associated with thread1.
I expected to see separate thread ids for threads 0,1 and the main thread. However, I was surprised to see something unexpected.
09-08 14:23:21.089: D/MQ(4514): Hi, the system is up! Today is: Sep 8, 2014 2:23:21 PM
09-08 14:23:21.099: V/MQ(4514): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 14:23:21.099: V/MQ(4514): BackgroundThread0. Thread id = 280 sent message 0
09-08 14:23:21.099: V/MQ(4514): MessageHandler on thread Thread id = 1 received message 0
Why does BackgroundThread1 have the same thread id as the main service thread id = 1?
I install it from Eclipse using Run As, and am starting it in a windows console window:
D:\>adb shell am startservice --user 0 -a android.intent.action.MAIN -n "com.sandbox.mq/.MainService"
Starting service: Intent { act=android.intent.action.MAIN cmp=com.sandbox.mq/.MainService }
--package com.sandbox.mq;
public class StartMainService extends Application {
final static String TAG = "MQ";
public void onCreate() {
super.onCreate();
Context context = getApplicationContext();
Log.d(TAG, "Hi, the system is up! Today is: " + DateFormat.getDateTimeInstance().format(new Date()));
}
}
--
public class MainService extends Service {
final static String TAG = "MQ";
BackgroundThread0 bthread0;
BackgroundThread1 bthread1;
public class MqBinder extends Binder {
public MqBinder(Context ctxt) {
Log.v(TAG, "MqBinder() " + "Thread id = "
+ Thread.currentThread().getId());
}
}
@Override
public IBinder onBind(Intent arg0) {
return new MqBinder(this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "onStartCommand(). I am INSIDE THE main sERVICE "
+ "Thread id = " + Thread.currentThread().getId());
bthread1 = new BackgroundThread1();
if (!bthread1.isAlive()) {
bthread1.start();
} else {
Log.v(TAG, "onStartCommand(). bthread1 was already started");
}
bthread0 = new BackgroundThread0();
if (!bthread0.isAlive()) {
bthread0.start();
} else {
Log.v(TAG, "onStartCommand(). bthread0 was already started");
}
return START_STICKY;
}
private class BackgroundThread0 extends Thread {
Handler b1Handler;
@Override
public void run() {
super.run();
b1Handler = bthread1.b1Handler;
Message msg = b1Handler.obtainMessage(MessageHandler.TYPE0);
b1Handler.sendMessage(msg);
Log.v(TAG, "BackgroundThread0. " + "Thread id = "
+ Thread.currentThread().getId() + " sent message "
+ msg.what);
}
}
private class BackgroundThread1 extends Thread {
public BackgroundThread1() {
super();
b1Handler = new MessageHandler();
}
Handler b1Handler;
@Override
public void run() {
super.run();
Looper.prepare();
Looper.loop();
}
}
private static class MessageHandler extends Handler {
static final int TYPE0 = 0;
static final int TYPE1 = 1;
static final int TYPE2 = 2;
public MessageHandler() {
}
@Override
public void handleMessage(Message msg) {
Log.v(TAG, "MessageHandler on thread " + "Thread id = "
+ Thread.currentThread().getId() + " received message "
+ msg.what);
switch (msg.what) {
case TYPE0:
break;
case TYPE1:
break;
case TYPE2:
break;
}
super.handleMessage(msg);
}
}
}
--
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sandbox.mq" >
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="19" />
<application
android:name="com.sandbox.mq.StartMainService"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:persistent="true"
android:theme="@style/AppTheme" >
<service android:name="com.sandbox.mq.MainService" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</service>
</application>
</manifest>
From eclipse, DDMS window
1 4514 Native 0 2 main
*2 4518 VmWait 0 0 GC
*3 4519 VmWait 0 0 Signal Catcher
*4 4520 Runnable 0 2 JDWP
*5 4521 VmWait 0 0 Compiler
*6 4522 Wait 0 0 ReferenceQueueDaemon
*7 4523 Wait 0 0 FinalizerDaemon
*8 4524 Wait 0 0 FinalizerWatchdogDaemon
9 4525 Native 0 0 Binder_1
10 4526 Native 0 0 Binder_2
11 4527 Native 0 0 Thread-279
After following TacBoss suggestion below, I get thread id=450 which is expected. thread id 451 likely completed.
1 11756 Native 1 1 main
*2 11760 VmWait 0 0 GC
*3 11761 VmWait 0 0 Signal Catcher
*4 11762 Runnable 0 0 JDWP
*5 11763 VmWait 0 0 Compiler
*6 11764 Wait 0 0 ReferenceQueueDaemon
*7 11765 Wait 0 0 FinalizerDaemon
*8 11766 Wait 0 0 FinalizerWatchdogDaemon
9 11767 Native 0 0 Binder_1
10 11768 Native 0 0 Binder_2
11 11770 Native 0 0 Thread-450
09-08 15:06:05.089: D/MQ(7931): Hi, the system is up! Today is: Sep 8, 2014 3:06:05 PM
09-08 15:06:05.089: V/MQ(7931): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 15:06:06.149: D/MQ(7946): Hi, the system is up! Today is: Sep 8, 2014 3:06:06 PM
09-08 15:06:06.149: V/MQ(7946): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 15:06:10.269: D/MQ(7964): Hi, the system is up! Today is: Sep 8, 2014 3:06:10 PM
09-08 15:06:10.269: V/MQ(7964): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 15:06:26.339: D/MQ(8110): Hi, the system is up! Today is: Sep 8, 2014 3:06:26 PM
09-08 15:06:26.339: V/MQ(8110): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 15:06:36.319: D/MQ(8166): Hi, the system is up! Today is: Sep 8, 2014 3:06:36 PM
09-08 15:06:36.319: V/MQ(8166): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 15:06:37.389: D/MQ(8182): Hi, the system is up! Today is: Sep 8, 2014 3:06:37 PM
09-08 15:06:37.389: V/MQ(8182): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 15:06:41.469: D/MQ(8200): Hi, the system is up! Today is: Sep 8, 2014 3:06:41 PM
09-08 15:06:41.469: V/MQ(8200): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 15:08:27.439: D/MQ(8577): Hi, the system is up! Today is: Sep 8, 2014 3:08:27 PM
09-08 15:08:27.439: V/MQ(8577): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 15:08:28.479: D/MQ(8593): Hi, the system is up! Today is: Sep 8, 2014 3:08:28 PM
09-08 15:08:28.489: V/MQ(8593): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 15:08:32.579: D/MQ(8612): Hi, the system is up! Today is: Sep 8, 2014 3:08:32 PM
09-08 15:08:32.579: V/MQ(8612): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 15:08:48.679: D/MQ(8630): Hi, the system is up! Today is: Sep 8, 2014 3:08:48 PM
09-08 15:08:48.679: V/MQ(8630): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 15:29:00.949: D/MQ(11756): Hi, the system is up! Today is: Sep 8, 2014 3:29:00 PM
09-08 15:29:00.949: V/MQ(11756): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 15:29:00.959: V/MQ(11756): BackgroundThread0. Thread id = 451 sent message 0
09-08 15:29:00.959: V/MQ(11756): MessageHandler on thread Thread id = 450 received message 0
--code changes
private class BackgroundThread1 extends Thread {
public BackgroundThread1() {
super();
start();
}
Handler b1Handler;
@Override
public void run() {
super.run();
Looper.prepare();
Looper looper = Looper.myLooper();
b1Handler = new MessageHandler(looper);
Looper.loop();
}
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "onStartCommand(). I am INSIDE THE main sERVICE "
+ "Thread id = " + Thread.currentThread().getId());
bthread1 = new BackgroundThread1();
// if (!bthread1.isAlive()) {
// bthread1.start();
// } else {
// Log.v(TAG, "onStartCommand(). bthread1 was already started");
// }
bthread0 = new BackgroundThread0();
if (!bthread0.isAlive()) {
bthread0.start();
} else {
Log.v(TAG, "onStartCommand(). bthread0 was already started");
}
return START_STICKY;
}
OK, this didn't pop straight up...
the problem is you create the handler within the constructor of the BGThread1 and this code is called from the main thread! and that is why the handler queue is also attached to the main thread.
public BackgroundThread1() {
super();
b1Handler = new MessageHandler(); // this is the main thread here...
}
if you want this handler to run on another thread you first have to do something like this:
private class BackgroundThread1 extends HandlerThread {
public BackgroundThread1() {
super();
...
Some code
...
start();
b1Handler = new MessageHandler(getLooper());
// this is the main thread here... but you create the handler with the looper of the new thread!
}
...
}
This would create the thread in the context you expect it to.
===================================================
An example of extending a "regular" thread:
class MyThread
extends Thread {
private Handler myHandler;
public MyThread() {
start();
}
@Override
public void run() {
Looper.prepare();
Looper looper = Looper.myLooper();
myHandler = new Handler(looper);
Looper.loop();
}
}
Now the handler runs on the new thread.
这篇关于为什么一个后台线程具有相同的线程ID为主要服务线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!