线程和线程池

2017-08-04  本文已影响6人  玄策

参考资料

Java多线程问题总结


目录


1)主线程和子线程


2)线程形态

2.1)AsyncTask

封装了线程池和Handler,主要方便在子线程中更新UI。

//Params 参数类型
//Progress 后台任务执行进度的类型
//Result 后台任务返回结果的类型
public abstract class AsyncTask<Params,Progress,Result>

//四个方法
//在主线程中执行,异步任务执行前,此方法被调用
onPreExecute()

//线程池中执行
doInBackground(Params...params){
  //更新进度,会调用onProgressUpdate()
  publicProgress(values);
}

//异步任务取消时被调用
onCancelled() 

//主线程中执行,执行进度发生改变调用
onProgressUpdate(Progress...values)

//主线程中执行,异步任务结束后会调用
onPostExecute(Result result)

注意:

//AsyncTask从Android3.0开始,默认情况下是串行执行的。为了让其在Android3.0及以上版本并行执行,可以采用
new mAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");

AsyncTask中有两个线程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一个Handler(InternalHandler),
SerialExecutor用于任务排队,而THREAD_POOL_EXECUTOR用于执行任务,InternalHandler则是将执行环境从线程池切换到主线程。


2.2)HandlerThread

HandlerThread继承了Thread,是一种可以使用Handler的Thread,其实它就是在run方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环。它有个具体使用场景,就是IntentService。
示例1:

// Step 1: 创建并启动HandlerThread线程,内部包含Looper
HandlerThread handlerThread = new HandlerThread("tgf");
handlerThread.start();

// Step 2: 创建Handler
Handler handler = new Handler(handlerThread.getLooper());

// Step 3: 发送消息
handler.post(new Runnable() {

        @Override
        public void run() {
            System.out.println("thread id="+Thread.currentThread().getId());
        }
    });

示例2:

class LooperThread extends Thread {
    public Handler mHandler;

    public void run() {
        Looper.prepare();
        // Step 1: 创建Handler
        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                //TODO 处理即将发送过来的消息
            }
        };

        Looper.loop();
    }
}

// Step 2: 创建并启动LooperThread线程,内部包含Looper
LooperThread looperThread = new LooperThread("tgf");
looperThread.start();

// Step 3: 发送消息
looperThread.mHandler.sendEmptyMessage(10);

2.3)IntentService

https://mp.weixin.qq.com/s?__biz=MzI0MjE3OTYwMg==&mid=401611665&idx=1&sn=9b6b1f2924d4adfe4e89a322ab53df9c&scene=21#wechat_redirect
IntentService是一个服务,内部采用HandlerThread来执行任务,HandlerThread是一个工作线程(子线程),其Handler的handleMessage会回调onHandleIntent并stopSelf,执行完毕自动退出。很像是一个后台线程,但却是一个服务,所以不容易被系统杀死。

@override
protected void onHandleIntent(Intent intent)

3)线程池

线程是操作系统调度的最小单元,它的创建和销毁都有相应的开销,当系统中存在大量线程时,系统会通过时间片轮转的方式调度。频繁的创建和销毁线程并不高效。正确的方式是采用线程池,一个线程池中缓存一定数量线程,减小开销。

线程池优点
避免重复创建销毁的开销
控制最大并发,避免大量线程争抢资源
有效的管理,如可以定时或指定间隔循环执行等

Java的线程池来源于Executor接口,真正实现为ThreadPoolExecutor

3.1)ThreadPoolExecutor

//corePoolSize 核心线程数,默认核心线程会在线程池内一直存活,除非设定allowCoreThreadTimeOut=true。
//maximumPoolSize 最大线程数,活动线程达到此峰值,后续任务将被阻塞
//keepAliveTime 非核心线程超时时间,超过则被回收
//unit keepAliveTime的时间单位,枚举TimeUnit.MILLSECONDS(毫秒), TimeUnit.SECONDS(秒)等。
//workQueue 任务队列,提交的任务runnable对象被存储在这
//threadFactory 线程工厂,为线程池创建新线程。
public ThreadPoolExecutor(
  int corePoolSize,
  int maximumPoolSize,
  long keepAliveTime,
  TimeUnit unit,
  BlockingQueue<Runnable> workQueue,
  ThreadFactory threadFactory
)
ThreadPoolExecutor执行任务的规则
当前线程数量<核心线程数,启动一个核心线程执行任务
当前线程数量>=核心线程数,将任务插入任务队列排队
任务队列满了,当前线程数<最大线程数,启动非核心线程执行任务
任务队列满了,当前线程数>=最大线程数,拒绝此任务

3.2)线程池的分类

分类 说明
FixedThreadPool 只有数量固定核心线程,无超时。所以能快速响应
CachedThreadPool 只有非核心线程,最大数量Integer.MAX_VALUE,空闲60秒后回收,适合大数量但耗时少任务
ScheduledThreadPool 核心线程数量固定,非核心线程数无限制,非核心闲置会立即回收,适合定时任务或固定周期重复任务
SingleThreadPool 只有一个核心线程,适合处理线程同步
//调用
ExecutorService a = Executor.newFixedThreadPool(4);
a.execute(runnable);
//源码
public static ExecutorService newFixedThreadPool(int nThreads){
  return new ThreadPoolExecutor(
    nThreads,
    nThreads,
    0L,
    TimeUnit.MILLSECONDS,
    new LinkedBlockingQueue<Runnable>()
  );
}

*CachedThreadPool

ExecutorService a = Executor.newCachedThreadPool();
a.execute(runnable);
public static ExecutorService newCachedThreadPool(){
  return new ThreadExecutor(
    0,
    Integer.MAX_VALUE,
    60L,
    TimeUnit.SECONDS,
    new SynchronousQueue<Runnable>()
  );
} 
ScheduledExecutorService a = Executor.newScheduledThreadPool(4);
//2000ms后执行runnable
a.schedule(runnable,2000,TimeUnit.MILLSECONDS);
//延迟10ms后,每隔1000ms执行一次runnable
a.scheduleAtFixedRate(runnable,10,1000,TimeUnit.MILLSECONDS);
public static ScheduledExecutor newScheduledThreadPool(int corePoolSize){
  return new ScheduledThreadPoolExecutor(corePoolSize);
} 

public ScheduledThreadPoolExecutor(int corePoolSize){
  super(corePoolSize,Integer.MAX_VALUE,0,NANOSECONDS,new DelayedWorkQueue());
}
ExecutorService a = Executor.newSingleThreadExecutor();
a.execute(runnable);
public static ExecutorService newSingleThreadExecutor(){
  return new FinalizableDelegatedExecutorService(
    new ThreadPoolExecutor(
      1,1,0L,TimeUnit.MILLSECONDS,
      new LinkedBlockingQueue<Runnable>()
    )
  );
} 
上一篇 下一篇

猜你喜欢

热点阅读