线程
android中的线程是执行Runnable
接口的Thread
。
代码如下
new Thread(new Runnable() {
@Override
public void run() {
//设置线程优先级,减少与UI线程的竞争
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
}
}).start();
代码执行在Runnable.run()里面。
通过android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND)
可以设置线程的优先级别,减少线程与UI线程的竞争。
[除此以外android还提供了更好的选择HandlerThread
, AsyncTask
, 和IntentService
.]
线程池
ThreadPoolExecutor能管理程序,开发者只需要把线程加入线程队列即可。
创建线程池的时候需要舒适化一些参数,见下面代码,摘抄自阿里巴巴的ANDROID开发手册
//获取可用cpu核数量
int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
//运行完后的存活时间
int KEEP_ALIVE_TIME = 1;
//运行完后的存活时间的单位
TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
//存放线程的队列
BlockingQueue taskQueue = new LinkedBlockingQueue();
ExecutorService executorService = new ThreadPoolExecutor(NUMBER_OF_CORES,
NUMBER_OF_CORES*2, KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT, taskQueue,
new BackgroundThreadFactory(), new DefaultRejectedExecutionHandler());
//执行任务
executorService.execute(new Runnable() {
@Override
public void run() {
}
});
//创建后台线程
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);
}
}
/*拒绝策略,当队列满后的处理方式,系统提供了
*AbortPolicy
*DiscardPolicy
*DiscardOldestPolicy
*CallerRunsPolicy
*/
private class DefaultRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
}
}
线程通信
线程间通讯分为两种,一种是和主线通讯,一种是后台线程之间通讯。
当与主线程通信的时候,是不可以阻塞主线程的,所以一般使用handler来通信。
先创建一个在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;
}
}
然后执行完耗时操作之后发消息给主线程去执行UI操作
executorService.execute(new Runnable() {
@Override
public void run() {
// 耗时操作
handler.obtainMessage(1).sendToTarget();
}
});
后台线程之间的通信主要涉及到同步与互斥。
如果在不同线程中操作同一数据,可能造成数据读写状态不同步,那么我们就需要在每一次的读写中锁住这个值。
如下两个线程。
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 释放之后才运行的。
再来看看wait和notify的应用。
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 开始的时候先wait,然后在线程B结束的时候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
会发现先执行A然后等待,接着开始制定B 等B notify之后又开始执行A;
以上就是线程的简单应用。