尝试创建2个后台线程并从thread0向thread1发送消息 由MessageHandler使用 android Looper和与thread1关联的消息队列来处理。
我希望看到线程0,1和主线程的单独线程ID。但是,我很惊讶地发现了一些意外的事情。
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
为什么BackgroundThread1与主服务线程id = 1具有相同的线程ID?
我使用Run As从Eclipse安装它,并在Windows控制台窗口中启动它:
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 }
- 包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>
来自eclipse, DDMS 窗口
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
按照下面的TacBoss建议后,我得到了预期的线程ID = 450。线程ID 451可能已完成。
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
- 代码更改
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;
}
答案 0 :(得分:1)
这是因为Service
生命周期是在主线程上处理的,即:Service
onCreate
,onStartCommand
,onDestruction
等方法被调用默认情况下为主线程,如android.app.Service's Class Overview
请注意,服务与其他应用程序对象一样,在其托管进程的主线程中运行。
答案 1 :(得分:1)
好的,这并没有直接弹出......
问题是你在BGThread1的构造函数中创建处理程序,并且从主线程调用此代码!这就是处理程序队列也附加到主线程的原因。
public BackgroundThread1() {
super();
b1Handler = new MessageHandler(); // this is the main thread here...
}
如果您希望此处理程序在另一个线程上运行,您首先必须执行以下操作:
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!
}
...
}
这将在您期望的上下文中创建线程。
=============================================== ====
扩展&#34;常规&#34;螺纹:
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();
}
}
现在处理程序在新线程上运行。