深入Android線程的相關問題解惑

來源:互聯網
上載者:User

一個應用只有一個線程
在預設情況下,更確切的講一個進程中只有一個線程,這跟其他語言,比如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更是如此,這個大家都懂得的!複製代碼 代碼如下:public class ActivityDemo extends Activity {
private static final String TAG = "ActivityDemo";
private Handler mMainHandler = new Handler(new Handler.Callback() {
public boolean handleMessage(Message msg) {
dumpThreadInfo();
return false;
}
});

@Override
protected void onCreate(Bundle savedInstanceState) {
dumpThreadInfo();
super.onCreate(savedInstanceState);

// add four buttons
LinearLayout layout = new LinearLayout(getApplication());
layout.setOrientation(LinearLayout.VERTICAL);
Button startService = new Button(getApplication());
startService.setText("Start a Service");
startService.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent i = new Intent(getApplication(), ServiceDemo.class);
startService(i);
}
});
layout.addView(startService);
Button startAnother = new Button(getApplication());
startAnother.setText("Start another Activity");
startAnother.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent i = new Intent(getApplication(), AnotherActivity.class);
startService(i);
}
});
layout.addView(startAnother);
Button startContentProvider = new Button(getApplication());
startContentProvider.setText("Start a ContentProvider");
startContentProvider.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
getContentResolver().query(ContentProviderDemo.CONTENT_URI, null, null, null, null);
}
});
layout.addView(startContentProvider);
Button startReceiver = new Button(getApplication());
startReceiver.setText("Start a BroadcastReceiver");
startReceiver.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent i = new Intent("android.action.start_broadcastreceiver_demo");
sendBroadcast(i);
}
});
layout.addView(startReceiver);
setContentView(layout);

mMainHandler.sendEmptyMessageDelayed(0, 500);
}

public void dumpThreadInfo() {
Thread.dumpStack();
Log.e(TAG, Thread.currentThread().toString());
Log.e(TAG, " " + getMainLooper());
}
}

複製代碼 代碼如下:public class AnotherActivity extends Activity {
private static final String TAG = "AnotherActivity";
private Handler mMainHandler = new Handler(getMainLooper(), new Handler.Callback() {
public boolean handleMessage(Message msg) {
// this will cause ANR
Log.e(TAG, "you know what this is very slow slow slow slow");
SystemClock.sleep(20 * 1000);
dumpThreadInfo();
return false;
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
dumpThreadInfo();
super.onCreate(savedInstanceState);

setTitle("this is another activity");
mMainHandler.sendEmptyMessageDelayed(0, 500);
}
@Override
protected void onDestroy() {
dumpThreadInfo();
super.onDestroy();
}
public void dumpThreadInfo() {
Thread.dumpStack();
Log.e(TAG, Thread.currentThread().toString());
Log.e(TAG, " " + getMainLooper());
}
}

複製代碼 代碼如下:public class ServiceDemo extends Service {
private Handler mMainHandler = new Handler(new Handler.Callback() {
public boolean handleMessage(Message msg) {
// this will cause ANR, too
Log.e(TAG, "this is very slow you know, slow slow");
SystemClock.sleep(20 * 1000);
dumpThreadInfo();
return false;
}
});
private static final String TAG = "ServiceDemo";
@Override
public IBinder onBind(Intent arg0) {
dumpThreadInfo();
return null;
}
@Override
public void onCreate() {
dumpThreadInfo();
super.onCreate();
mMainHandler.sendEmptyMessageDelayed(0, 500);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
dumpThreadInfo();
return super.onStartCommand(intent, flags, startId);
}

public void dumpThreadInfo() {
Thread.dumpStack();
Log.e(TAG, Thread.currentThread().toString());
Log.e(TAG, " " + getMainLooper());
}
}

複製代碼 代碼如下:public class ContentProviderDemo extends ContentProvider {
public static final Uri CONTENT_URI = Uri.parse("content://com.hilton.effectiveandroid.app/content");
private static final String TAG = "ContentProviderDemo";
@Override
public int delete(Uri arg0, String arg1, String[] arg2) {
dumpThreadInfo();
return 0;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
dumpThreadInfo();
return null;
}
@Override
public boolean onCreate() {
dumpThreadInfo();
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
dumpThreadInfo();
// it will cause ANR of course
Log.e(TAG, "this is very slow, you know that");
SystemClock.sleep(20 * 1000);
return null;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
dumpThreadInfo();
return 0;
}

public void dumpThreadInfo() {
Thread.dumpStack();
Log.e(TAG, Thread.currentThread().toString());
}
@Override
public String getType(Uri arg0) {
return null;
}
}

複製代碼 代碼如下:public class BroadcastReceiverDemo extends BroadcastReceiver {
private static final String TAG = "BroadcastReceiverDemo";
@Override
public void onReceive(Context context, Intent intent) {
Log.e(TAG, "intent is " + intent);
dumpThreadInfo();
}

public void dumpThreadInfo() {
Thread.dumpStack();
Log.e(TAG, Thread.currentThread().toString());
}
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.