Android线程解惑

一个应用只有一个线程

在默认情况下, 更确切的讲一个进程中只有一个线程,这跟其他语言,比如C/C++,Java等是一致。也就是说在Android应用程序里面一个进程只有一个线程,所有组件都运行在一个线程里面!
当应用程序启动时,系统会为其创建一个进程,也会创建一个线程名字叫做main,所有其所属组件的创建,系统事件的处理,系统的回调等一切应用相关的事情都运行在此名叫main的线程中。此线程即为常说的主线程(main thread)。俗称的UI线程(UI thread)也是它,因为只有主线程可以操作UI相关的事情,所以有人把主线程也称作UI线程,但这并不是正确的说法,因为Service所属的线程也可以操作Toast,但是Service并没有UI。为什么非主线程不能操作UI呢?因为对UI操作常常会引发系统的回调,所以如果允许第三线程来操作可能会引发系统回调的紊乱,进而会打乱整个框架的时序!
这里要特别注意的就是同一个进程中的所有组件运行在同一个线程中,Activiy,Service,BoradcastReceiver和ContentProvider都运行在主线程中。

最容易引起误解的就是Service,文档和常识都会认为Service是放在后台用于操作费时运算的,但是实则不然,如果你在Service中做费时操作,同样会引发臭名昭著的ANR(Application Not Responding)。所以如果想把Service当做一个Server,必须在Service用HandlerThread或Thread创建一个Worker线程!

Activity也是一样的,你startActivity()后,开启了一个新的Activity,但它们都运行在同一个线程中,所以你还是不能在原Activity中做费时操作!也即在调用startActivity()开启了一个新的Activity后,或者在onPause(), onStop(), onDestroy()中做费时操作会引发ANR。

对于ContentProvider也是一样的,如果跟其他组件在同一进程内,那么调用ContentResolver的方法会相当于直接调用ContentProvider的方法。如果是在另外一个进程中,虽是通过IPC,但也是同步的,因为IBinder的同步的,也即调用ContentResolver时会把调用者的进程挂起,等待ContentProvider的进程操作结束,再把结果传给调用者进程!所以,如果ContentProvider中有费时操作,或者会同步锁数据库等,也一定要注意ANR的发生!
所以一定要记住:一个进程只有一个线程,所有组件都运行在主线程中。
因此,如果有费时操作,必须要创建Worker线程!

实例

下面有一个小实例,一个应用中有五个组件:2个Activity,一个Service,一个ContentProvider和一个BroadcastReceiver。在每个组件的方法中都有打印所属线程信息,另外对于Activity,Service和ContentProvider如果做费时操作会引发ANR,对于BroadcastReceiver更是如此,这个大家都懂得的!

[java]  view plain copy print ?
  1. public class ActivityDemo extends Activity {  
  2.   
  3.     private static final String TAG = "ActivityDemo";  
  4.   
  5.     private Handler mMainHandler = new Handler(new Handler.Callback() {  
  6.     public boolean handleMessage(Message msg) {  
  7.         dumpThreadInfo();  
  8.         return false;  
  9.     }  
  10.     });  
  11.       
  12.     @Override  
  13.     protected void onCreate(Bundle savedInstanceState) {  
  14.     dumpThreadInfo();  
  15.     super.onCreate(savedInstanceState);  
  16.       
  17.     // add four buttons  
  18.     LinearLayout layout = new LinearLayout(getApplication());  
  19.     layout.setOrientation(LinearLayout.VERTICAL);  
  20.     Button startService = new Button(getApplication());  
  21.     startService.setText("Start a Service");  
  22.     startService.setOnClickListener(new View.OnClickListener() {  
  23.         public void onClick(View v) {  
  24.         Intent i = new Intent(getApplication(), ServiceDemo.class);  
  25.         startService(i);  
  26.         }  
  27.     });  
  28.     layout.addView(startService);  
  29.     Button startAnother = new Button(getApplication());  
  30.     startAnother.setText("Start another Activity");  
  31.     startAnother.setOnClickListener(new View.OnClickListener() {  
  32.         public void onClick(View v) {  
  33.         Intent i = new Intent(getApplication(), AnotherActivity.class);  
  34.         startService(i);  
  35.         }  
  36.     });  
  37.     layout.addView(startAnother);  
  38.     Button startContentProvider = new Button(getApplication());  
  39.     startContentProvider.setText("Start a ContentProvider");  
  40.     startContentProvider.setOnClickListener(new View.OnClickListener() {  
  41.         public void onClick(View v) {  
  42.         getContentResolver().query(ContentProviderDemo.CONTENT_URI, nullnullnullnull);  
  43.         }  
  44.     });  
  45.     layout.addView(startContentProvider);  
  46.     Button startReceiver = new Button(getApplication());  
  47.     startReceiver.setText("Start a BroadcastReceiver");  
  48.     startReceiver.setOnClickListener(new View.OnClickListener() {  
  49.         public void onClick(View v) {  
  50.         Intent i = new Intent("android.action.start_broadcastreceiver_demo");  
  51.         sendBroadcast(i);  
  52.         }  
  53.     });  
  54.     layout.addView(startReceiver);  
  55.     setContentView(layout);  
  56.       
  57.     mMainHandler.sendEmptyMessageDelayed(0500);  
  58.     }  
  59.     
  60.     public void dumpThreadInfo() {  
  61.     Thread.dumpStack();  
  62.     Log.e(TAG, Thread.currentThread().toString());  
  63.     Log.e(TAG, " " + getMainLooper());  
  64.     }  
  65. }  
[java]  view plain copy print ?
  1. public class AnotherActivity extends Activity {  
  2.     private static final String TAG = "AnotherActivity";  
  3.     private Handler mMainHandler = new Handler(getMainLooper(), new Handler.Callback() {  
  4.         public boolean handleMessage(Message msg) {  
  5.             // this will cause ANR  
  6.             Log.e(TAG, "you know what this is very slow slow slow slow");  
  7.             SystemClock.sleep(20 * 1000);  
  8.             dumpThreadInfo();  
  9.             return false;  
  10.         }  
  11.     });  
  12.     @Override  
  13.     protected void onCreate(Bundle savedInstanceState) {  
  14.     dumpThreadInfo();  
  15.     super.onCreate(savedInstanceState);  
  16.       
  17.     setTitle("this is another activity");  
  18.     mMainHandler.sendEmptyMessageDelayed(0500);  
  19.     }  
  20.   
  21.     @Override  
  22.     protected void onDestroy() {  
  23.     dumpThreadInfo();  
  24.     super.onDestroy();  
  25.     }  
  26.   
  27.     public void dumpThreadInfo() {  
  28.     Thread.dumpStack();  
  29.     Log.e(TAG, Thread.currentThread().toString());  
  30.     Log.e(TAG, " " + getMainLooper());  
  31.     }  
  32. }  
[java]  view plain copy print ?
  1. public class ServiceDemo extends Service {  
  2.     private Handler mMainHandler = new Handler(new Handler.Callback() {  
  3.         public boolean handleMessage(Message msg) {  
  4.             // this will cause ANR, too  
  5.             Log.e(TAG, "this is very slow you know, slow slow");  
  6.             SystemClock.sleep(20 * 1000);  
  7.             dumpThreadInfo();  
  8.             return false;  
  9.         }  
  10.     });  
  11.     private static final String TAG = "ServiceDemo";  
  12.     @Override  
  13.     public IBinder onBind(Intent arg0) {  
  14.     dumpThreadInfo();  
  15.     return null;  
  16.     }  
  17.   
  18.     @Override  
  19.     public void onCreate() {  
  20.     dumpThreadInfo();  
  21.     super.onCreate();  
  22.     mMainHandler.sendEmptyMessageDelayed(0500);  
  23.     }  
  24.   
  25.     @Override  
  26.     public int onStartCommand(Intent intent, int flags, int startId) {  
  27.     dumpThreadInfo();  
  28.     return super.onStartCommand(intent, flags, startId);  
  29.     }  
  30.       
  31.     public void dumpThreadInfo() {  
  32.     Thread.dumpStack();  
  33.     Log.e(TAG, Thread.currentThread().toString());  
  34.     Log.e(TAG, " " + getMainLooper());  
  35.     }  
  36. }  

[java]  view plain copy print ?
  1. public class ContentProviderDemo extends ContentProvider {  
  2.     public static final Uri CONTENT_URI = Uri.parse("content://com.hilton.effectiveandroid.app/content");  
  3.     private static final String TAG = "ContentProviderDemo";  
  4.     @Override  
  5.     public int delete(Uri arg0, String arg1, String[] arg2) {  
  6.     dumpThreadInfo();  
  7.     return 0;  
  8.     }  
  9.   
  10.     @Override  
  11.     public Uri insert(Uri uri, ContentValues values) {  
  12.     dumpThreadInfo();  
  13.     return null;  
  14.     }  
  15.   
  16.     @Override  
  17.     public boolean onCreate() {  
  18.     dumpThreadInfo();  
  19.     return false;  
  20.     }  
  21.   
  22.     @Override  
  23.     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {  
  24.     dumpThreadInfo();  
  25.     // it will cause ANR of course  
  26.     Log.e(TAG, "this is very slow, you know that");  
  27.     SystemClock.sleep(20 * 1000);  
  28.     return null;  
  29.     }  
  30.   
  31.     @Override  
  32.     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {  
  33.     dumpThreadInfo();  
  34.     return 0;  
  35.     }  
  36.       
  37.     public void dumpThreadInfo() {  
  38.     Thread.dumpStack();  
  39.     Log.e(TAG, Thread.currentThread().toString());  
  40.     }  
  41.   
  42.     @Override  
  43.     public String getType(Uri arg0) {  
  44.     return null;  
  45.     }  
  46. }  

[java]  view plain copy print ?
  1. public class BroadcastReceiverDemo extends BroadcastReceiver {  
  2.   
  3.     private static final String TAG = "BroadcastReceiverDemo";  
  4.     @Override  
  5.     public void onReceive(Context context, Intent intent) {  
  6.     Log.e(TAG, "intent is " + intent);  
  7.     dumpThreadInfo();  
  8.     }  
  9.       
  10.     public void dumpThreadInfo() {  
  11.     Thread.dumpStack();  
  12.     Log.e(TAG, Thread.currentThread().toString());  
  13.     }  
  14. }  

转自:http://blog.csdn.net/hitlion2008/article/details/7657629

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值