一:简介
在操作系系统中,线程是操作系统调度的最小单元。线程是一种受限的系统资源,线程不可能无限制地产生,并且线程的创建和销毁都会有相应的开销。如果在一个进程中频繁地创建和销毁线程,显然这不是高效的做法。
正确的做法是:创建线程池,一个线程池中会缓存一定数量的线程。通过线程池可以品便因为频繁创建和销毁线程所带来的系统开销。
二:线程的形态
除了Thread本身意外,还包含AsyncTask、HandlerThread、IntentService
2.1 AsyncTask
简介:AsyncTask封装了线程池和Handler,可以方便开发者在子线程中更新UI
public class AsyncTaskDemoActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_async_task_demo);
findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
test();
}
});
}
/**
* 通过这个方法,可以证明
* 1.execute();方法是串行的
* 2.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);是并行的
*/
private void test() {
new MyAsyncTask("task1").execute();
new MyAsyncTask("task2").execute();
new MyAsyncTask("task3").execute();
new MyAsyncTask("task4").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new MyAsyncTask("task5").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new MyAsyncTask("task6").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
/**
* public abstract class AsyncTask<Params, Progress, Result>,这三个泛型参数
* params:表示参数的类型
* progress:后台任务的执行进度类型
* result:后台任务的返回结果类型
*/
private class MyAsyncTask extends AsyncTask<String, Integer, String> {
private String mTaskName = "MyAsyncTask";
public MyAsyncTask(String name) {
super();
this.mTaskName = name;
}
/**
* 在主线程中执行,在异步任务执行之前,这个方法会被调用,一般用于做一些准备工作。
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Log.e("===:", format.format(new Date()));
}
/**
* 在线程池中执行,此方法用于执行异步任务。
* 1.params参数用于表示异步任务的输入参数。
* 2.在此方法中,可以通过publishProgress()方法来更新任务的进度。publishProgress()会调用onProgressUpdate方法
* 3.需要返回计算结果给onPostExecute();
*/
@Override
protected String doInBackground(String... params) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return mTaskName;
}
/**
* 在主线中执行,当后台任务的执行进度发生变化时调用此方法
*/
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
/**
* 在主线程中执行,在异步任务执行之后,此方法会调用。
* 其中,result是后台任务的返回值。即:doInBackground的返回值
*/
@Override
protected void onPostExecute(String value) {
super.onPostExecute(value);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Log.e("===:", value + " " + format.format(new Date()));
}
/**
* 异步任务被取消时调用,onPostExecute()不会被调用;
*/
@Override
protected void onCancelled(String value) {
super.onCancelled(value);
}
/**
*
*/
@Override
protected void onCancelled() {
super.onCancelled();
}
}
}
2.2HandlerThread:是一个具有消息循环的线程,在他的内部可以使用Handler
2.3IntentService
/**
* desc 用于执行高优先级的后台任务
* service是运行在主线程,IntentService是运行在子线程
* 优势:
* 1.可用于执行后台耗时的任务 —IntentService是服务导致它的优先级比单纯的线程要高很多。所以适合执行一些高优先级的后台任务
* 2.当任务执行完之后会自动停止
* onHandleIntent((Intent)msg.obj);这个方法执行完之后,会调用 stopSelf(msg.arg1);
* stopSelf();源码是调用 stopSelf(-1);因为是-1会立即结束当前的任务
* stopSelf(msg.arg1);会传递服务启动的数量,会等待所有消息处理完后在stop
*/
public class MyIntentService extends IntentService {
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
private static String TAG = "MyIntentService";
public MyIntentService(String name) {
super(TAG);
TAG = name;
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
SystemClock.sleep(1000*6);//调用的也是Thread.sleep()
Log.e("===", Thread.currentThread().getName());
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
三:线程池
public class ThreadDemoActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_thread_demo);
Runnable runnable = new Runnable() {
@Override
public void run() {
SystemClock.sleep(2000);
}
};
}
/**
* 优势:主要用于执行定时任务和具有固定周期的重复任务
* 原因:核心线程时固定的,非核心没有限制,当非核心线程闲置时,10毫秒会被回收;
*/
private void scheduledThreadPool(Runnable runnable) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4);
//立即执行
scheduledThreadPool.execute(runnable);
//1000ms后执行
scheduledThreadPool.schedule(runnable, 1000, TimeUnit.MILLISECONDS);
//延迟1000ms后,每隔100ms执行一次runnable
scheduledThreadPool.scheduleAtFixedRate(runnable, 1000, 100, TimeUnit.MILLISECONDS);
}
/**
* 优势:确保所有的任务都在同一个线程中按顺序执行,统一所有的外界任务到一个线程中,这使得这些任务之间不需要处理线程同步的问题;
* 原因:只有一个核心线程,最大线程数为1
*/
private void singleThreadExecutor(Runnable runnable) {
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
singleThreadExecutor.execute(runnable);
}
/**
* 优势:比较适合执行大量的耗时任务较少的任务
* CachedThreadPool:只有非核心线程,并且最大线程数为Integer.MAX_VALUE,超时时间为60s,超过60s的闲置线程就会被回收;
* 当线程池中的线程处于活动状态时,会创建新线程来处理新任务,否则会利用空闲线程来处理新任务;
*/
private void cachedThreadPool(Runnable runnable) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.execute(runnable);
}
/**
* 优势:能够更加快速地相应外界的请求
* 原因:FiexedThreadPool是一种线程数量固定的线程池,当线程处于空闲状态时,他们并不会被回收,除非线程池被关闭了。
* 当所有的线程都处于活动状态时,新任务会处于等待状态;
* 由于FixedThreadPool只有核心线程,并且这些核心线程并不会被回收,所以可以更加快读地响应外界的请求;
*/
private void newFixedThreadPool(Runnable runnable) {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
fixedThreadPool.execute(runnable);
}
}
四:自定义线程池
/**
* desc 使用线程池的好处
* 1.复用已经创建好的线程,避免频繁创建线程进而导致的GC garbage collection\避免因为线程的创建和销毁所带来的性能开销
* 2.能有效控制线程池的最大并发数,避免大量的线程因互相抢占资源而导致的阻塞
* 3.能够对线程进行简单的管理,比如定时执行、取消执行、指定间隔循环执行等功能
* int corePoolSize:线程中核心线程的数据
* int maximumPoolSize :线程中最大线程的数量
* long keepAliveTime:非核心线程的超时时长
* TimeUnit unit:第三个参数的单位
* BlockingQueue workQueue,线程池中的任务队列,该队列用来存储已经被提交但是尚未执行的任务。
* 存储在这里面的任务是由:ThreadPoolExecutor的execute方法提交来的
* ThreadFactory threadFactory,为线程池提供创建新线程的功能
* RejectedExecutionHandler handler:拒绝策略,当线程无法执行新任务时,默认情况下,当线程池无法处理新线程时,
* 会抛出一个RejectedExecutionException
*
* 1.shutDown() 关闭线程池,不影响已经提交的任务
*
* 2.shutDownNow() 关闭线程池,并尝试去终止正在执行的线程
*
* 3.allowCoreThreadTimeOut(boolean value) 允许核心线程闲置超时时被回收
*
* 4.submit 一般情况下我们使用execute来提交任务,但是有时候可能也会用到submit,使用submit的好处是submit有返回值
*/
public class ThreadManager {
private static ThreadManager instance;
private ThreadPoolProxy poolProxy;
//手机CPU数
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE = 1;
private TimeUnit timeUnit = TimeUnit.MILLISECONDS;
private ThreadManager() {
}
public static ThreadManager getInstance() {
if (instance == null) {
instance = new ThreadManager();
}
return instance;
}
public synchronized ThreadPoolProxy createPool() {
if (poolProxy == null) {
poolProxy = new ThreadPoolProxy(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, 5000, timeUnit);
}
return poolProxy;
}
public class ThreadPoolProxy {
private ThreadPoolExecutor pool;
private int corePoolSize; //线程数
private int maximumPoolSize; //线程满了后额外开的线程窗口
private long keepAliveTime;//没有线程执行时存活时间
private TimeUnit timeUnit;
public ThreadPoolProxy(int corePoolSize, int maximumPoolSize, int keepAliveTime, TimeUnit timeUnit) {
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.keepAliveTime = keepAliveTime;
this.timeUnit = timeUnit;
}
/**
* 执行线程
*/
public void exexute(Runnable runnable) {
if (pool == null) {
BlockingQueue<Runnable> workQuene = new LinkedBlockingQueue<>(10);
pool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, timeUnit, workQuene);
}
pool.execute(runnable);
}
/**
* 取消线程
*/
public void cancel(Runnable runnable) {
if (pool != null) {
pool.remove(runnable);
}
}
}
}