Android 线程和线程池

一:简介
在操作系系统中,线程是操作系统调度的最小单元。线程是一种受限的系统资源,线程不可能无限制地产生,并且线程的创建和销毁都会有相应的开销。如果在一个进程中频繁地创建和销毁线程,显然这不是高效的做法。
正确的做法是:创建线程池,一个线程池中会缓存一定数量的线程。通过线程池可以品便因为频繁创建和销毁线程所带来的系统开销。
二:线程的形态
除了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);
        }
    }
}

}


猜你喜欢

转载自blog.csdn.net/weixin_37292229/article/details/78472050
今日推荐