線程
android中的線程是執(zhí)行Runnable
接口的Thread
。
代碼如下
new Thread(new Runnable() {
@Override
public void run() {
//設(shè)置線程優(yōu)先級(jí)吉拳,減少與UI線程的競(jìng)爭(zhēng)
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
}
}).start();
代碼執(zhí)行在Runnable.run()里面萎战。
通過android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND)
可以設(shè)置線程的優(yōu)先級(jí)別绣夺,減少線程與UI線程的競(jìng)爭(zhēng)纽门。
[除此以外android還提供了更好的選擇HandlerThread
, AsyncTask
, 和IntentService
.]
線程池
ThreadPoolExecutor能管理程序伤疙,開發(fā)者只需要把線程加入線程隊(duì)列即可悼吱。
創(chuàng)建線程池的時(shí)候需要舒適化一些參數(shù)慎框,見下面代碼,摘抄自阿里巴巴的ANDROID開發(fā)手冊(cè)
//獲取可用cpu核數(shù)量
int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
//運(yùn)行完后的存活時(shí)間
int KEEP_ALIVE_TIME = 1;
//運(yùn)行完后的存活時(shí)間的單位
TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
//存放線程的隊(duì)列
BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<Runnable>();
ExecutorService executorService = new ThreadPoolExecutor(NUMBER_OF_CORES,
NUMBER_OF_CORES*2, KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT, taskQueue,
new BackgroundThreadFactory(), new DefaultRejectedExecutionHandler());
//執(zhí)行任務(wù)
executorService.execute(new Runnable() {
@Override
public void run() {
}
});
//創(chuàng)建后臺(tái)線程
private class BackgroundThreadFactory implements ThreadFactory {
@Override
public Thread newThread(@NonNull final Runnable r) {
Runnable wrapperRunnable = new Runnable() {
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
r.run();
}
};
return new Thread(wrapperRunnable);
}
}
/*拒絕策略后添,當(dāng)隊(duì)列滿后的處理方式笨枯,系統(tǒng)提供了
*AbortPolicy
*DiscardPolicy
*DiscardOldestPolicy
*CallerRunsPolicy
*/
private class DefaultRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
}
}
線程通信
線程間通訊分為兩種,一種是和主線通訊遇西,一種是后臺(tái)線程之間通訊馅精。
當(dāng)與主線程通信的時(shí)候,是不可以阻塞主線程的粱檀,所以一般使用handler來(lái)通信洲敢。
先創(chuàng)建一個(gè)在UI線程的Handler
Handler handler = new UiHandler();
private static class UiHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
//更新UI等操作
break;
default:
break;
}
}
然后執(zhí)行完耗時(shí)操作之后發(fā)消息給主線程去執(zhí)行UI操作
executorService.execute(new Runnable() {
@Override
public void run() {
// 耗時(shí)操作
handler.obtainMessage(1).sendToTarget();
}
});
后臺(tái)線程之間的通信主要涉及到同步與互斥。
如果在不同線程中操作同一數(shù)據(jù)茄蚯,可能造成數(shù)據(jù)讀寫狀態(tài)不同步压彭,那么我們就需要在每一次的讀寫中鎖住這個(gè)值。
如下兩個(gè)線程渗常。
class RunableA implements Runnable{
@Override
public void run() {
synchronized (MainActivity.class){
Log.d("hah","A start");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("hah","A end");
}
}
}
class RunableB implements Runnable{
@Override
public void run() {
synchronized (MainActivity.class){
Log.d("hah","b start");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("hah","b END");
}
}
}
executorService.execute(new RunableA());
executorService.execute(new RunableB());
打印如下:
14:56:53.083 3382-3395/activity.activitytest D/bruce: A start
14:56:55.083 3382-3395/activity.activitytest D/bruce: A end
14:56:55.153 3382-3396/activity.activitytest D/bruce: b start
14:56:57.153 3382-3396/activity.activitytest D/bruce: b END
可見B 是等 A 釋放之后才運(yùn)行的壮不。
再來(lái)看看wait和notify的應(yīng)用。
class RunableA implements Runnable{
@Override
public void run() {
synchronized (MainActivity.class) {
Log.d("bruce", "A wait");
try {
MainActivity.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("bruce", "A start");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("bruce", "A end");
}
}
}
class RunableB implements Runnable{
@Override
public void run() {
synchronized (MainActivity.class) {
Log.d("bruce", "b start");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("bruce", "b END");
MainActivity.class.notify();
}
}
}
線程A 開始的時(shí)候先wait皱碘,然后在線程B結(jié)束的時(shí)候notify
打印如下:
15:17:34.423 4365-4378/? D/bruce: A wait
15:17:34.423 4365-4379/? D/bruce: b start
15:17:36.423 4365-4379/activity.activitytest D/bruce: b END
15:17:36.423 4365-4378/activity.activitytest D/bruce: A start
15:17:38.433 4365-4378/activity.activitytest D/bruce: A end
會(huì)發(fā)現(xiàn)先執(zhí)行A然后等待询一,接著開始制定B 等B notify之后又開始執(zhí)行A;
以上就是線程的簡(jiǎn)單應(yīng)用。