1. 前言
更多内容请查看android生态之应用篇
直接进入主题,Thread即线程,Process即进程,经常会有人分不清楚两者,先来看官方的解释:
进程是资源分配的最小单位,线程是CPU调度的最小单位。
这个回答可能比较抽象不好被理解,这边就打个最简单的比方:
在工厂中,进程就像一个车间,这个车间可以有不同的流水线,或者仅有一条流水线,这个流水线就指的是线程。线程一般职能单一,就像一条流水线的话就只生产一种产品,但是进程的话就跟车间一样,他可以包含有不同的流水线,它能产生不同种类的产品。再通俗来讲:进程就是老子,管着他众多的线程儿子。
2. Thread
2.2 线程的创建
创建Thread有两种比较常见的方式:
new Thread(new Runnable() {
@Override
public void run() {
}
}).start();
new Thread(){
@Override
public void run() {
super.run();
}
}.start();
2.2 线程池
创建线程可以提高程序的执行效率,但是也不能无限的创建线程,这个跟系统设置有关,存在最大线程数限制。还有就是创建过多线程会导致CPU资源紧张,并且如果线程得不到释放的话,这样就会明显的感觉到程序变“卡”。重复线程创建和销毁的过程会给系统造成巨大的消耗,所以就很有必要设计一个“管理者”的存在,他的作用包括:
1.管理并复用线程、控制最大并发数等
2.实现任务线程队列缓存策略和拒绝机制
3.实现某些与时间相关的功能,如定时执行、周期执行等
4.隔离线程环境
这也就引出了线程池这一“管理者”的角色。
这边提供一个自定义线程池的模板,如果想要清楚线程池更多的细节的话,如参数含义,以及线程池种类等,这个自行百度,不再赘述:
public class BHThreadPool {
ThreadPoolExecutor threadPoolExecutor;
int corePoolSize;
int maximumPollSize;
long keepAliveTime;
public static BHThreadPool instance;
public static BHThreadPool getInstance() {
if (instance == null) {
instance = new BHThreadPool(1,1,1000);
}
return instance;
}
public BHThreadPool(int corePoolSize, int maximumPollSize, long keepAliveTime){
this.corePoolSize = corePoolSize;
this.maximumPollSize = maximumPollSize;
this.keepAliveTime = keepAliveTime;
}
public ThreadPoolExecutor initExecutor(){
if (threadPoolExecutor == null) {
synchronized (BHThreadPool.class){
TimeUnit unit = TimeUnit.MILLISECONDS;
ThreadFactory threadFactory = Executors.defaultThreadFactory();
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
threadPoolExecutor = new ThreadPoolExecutor(
//核心线程数
corePoolSize,
//最大线程数
maximumPollSize,
//保持时间
keepAliveTime,
//保持时间对应的单位
unit,
workQueue,
threadFactory,
handler
);
}
}
return threadPoolExecutor;
}
/**
* 执行任务
*/
public void executeTask(Runnable runnable){
initExecutor();
threadPoolExecutor.execute(runnable);
}
/**
* 提交任务
*/
public Future<?> commitTask(Runnable runnable){
initExecutor();
return threadPoolExecutor.submit(runnable);
}
/**
* 删除任务
* removeTask()方法起作用有一个必要的前提,就是这个任务还没有开始执行,
* 如果已经开始执行了,就停止不了该任务了,这个方法就不会起作用
*/
public void removeTask(Runnable runnable){
initExecutor();
threadPoolExecutor.remove(runnable);
}
/**
* 关闭线程池操作的方法
*/
public void closeThread(){
threadPoolExecutor.shutdownNow();
}
/**
* 线程池用法
* 1 BHThreadPool 线程池对象
* 2 runnable
* 3 将runnable添加到BHThreadPool线程池中去
*/
// BHThreadPool BHThreadPool = new BHThreadPool(1,1,1000);
// Runnable runnable = new Runnable() {
// @Override
// public void run() {
// 可执行发动handler操作
// Log.e("log", "子线程操作");
// }
// };
//
// BHThreadPool.executeTask(runnable);
}
2.3 线程之间的交流
这边提它一下这个线程之间的交流,这个问题开发的时候会比较常见。我们可能在处理网络数据或者其他耗时操作的逻辑的时候,通常会独自开一个线程进行处理,然后当线程完成之后再告诉UI线程进行UI更新操作,这个就需要用到Handler这个线程交流的使者。
这边也只提一下如何使用handler,如果想要了解handler的更多细节的话,可以自行百度,或者看之前我写的有关handler的文章:浅谈android应用之消息机制
使用handler的常见有两种方式:
一,采用sendEmptyMessageDelayed
package com.awaitu.easymusic.view;
import android.os.Bundle;
import com.awaitu.easymusic.R;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.Window;
public class SplashActivity extends Activity {
private static final int SPLASH_TIME = 3000;
@SuppressLint("HandlerLeak") private Handler splashHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1)
{
SplashActivity.this.stopSplash();
this.removeMessages(1);
}
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_splash);
splashHandler.sendEmptyMessageDelayed(1, SplashActivity.SPLASH_TIME);
}
private void stopSplash()
{
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
splashHandler.sendEmptyMessage(1);
return true;
}
return super.onTouchEvent(event);
}
}
二,采用postdelay
package com.awaitu.easymusic.view;
import android.os.Bundle;
import com.awaitu.easymusic.R;
import android.app.Activity;
import android.content.Intent;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.Window;
public class SplashActivity extends Activity {
private static final int SPLASH_TIME = 3000;
Handler mhandler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_splash);
mhandler = new Handler();
mhandler.postDelayed(new SplashHandler(),SPLASH_TIME);
}
private class SplashHandler implements Runnable{
public void run(){
startActivity(new Intent(getApplication(),MainActivity.class));
finish();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
mhandler.post(new SplashHandler());
return true;
}
return super.onTouchEvent(event);
}
}
3. Process
3.1 进程的创建
在android系统中,一个应用程序实质就是一个进程,他的启动是由虚拟机fork出来的,原理跟linux创建进程的过程类似。
3.3 IPC方式
这里的内容直接看我这篇文章就差不多了:浅谈android应用之IPC。