从零开始编写图片加载库(三)之线程池图片下载
来源:互联网 发布:2016年非公经济数据 编辑:程序博客网 时间:2024/05/21 17:14
1.简介
我们知道在开发应用程序时候,有时候下载图片的操作是很多的,但是我们又不能不能在UI线程里面去执行网络操作,并且android系统要求我们在执行完网络操作后更新UI,前面两篇文章介绍了通过AsyncTask和Handler+Thread的方式更新UI。这篇文章介绍通过线程池的方式处理线程。
2.ExecutorService的介绍
An {@code ExecutorService} can be shut down, which will cause it to reject new tasks. Two different methods are provided for shutting down an {@code ExecutorService}. The {@link #shutdown} method will allow previously submitted tasks to execute before terminating, while the {@link #shutdownNow} method prevents waiting tasks from starting and attempts to stop currently executing tasks. Upon termination, an executor has no tasks actively executing, no tasks awaiting execution, and no new tasks can be submitted. An unused {@code ExecutorService} should be shut down to allow reclamation of its resources.(摘自源代码)
意思是ExecutorService可以停止执行当前线程,并且子方法shutdown和shutdownnow的停止方式不一样,shutdown会等当前任务执行完再停止,shutdowndow是立即停止。
2.1NetworkService、Executors和ThreadPoolExecutor之间的关系
ThreadPoolExecutor继承AbstractExecutorService,而AbstractExecutorService实现了NetworkService里面定义的方法,ThreadPoolExecutor是创建线程池的工人,NetworkService有点像包工头,接活然后把活给ThreadPoolExecutor干,Executors主要是管理NetworkService的一些需求然后将需求直接传达给ThreadPoolExecutor。
Executors里面提供的一个创建NetworkService方法。
public static ExecutorService newFixedThreadPool(int nThreads){ return new ThreadPoolExecutor(nThreads,nThreads, 0L,TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
2.2一个NetworkService实例
class NetworkService implements Runnable { private final ServerSocket serverSocket; private final ExecutorService pool; public NetworkService(int port, int poolSize) throws IOException { serverSocket = new ServerSocket(port); //创建一个线程池 pool = Executors.newFixedThreadPool(poolSize); } public void run() { // run the service try { for (; ; ) { //将当前任务抛到线程池当中执行 pool.execute(new Handler(serverSocket.accept())); } } catch (IOException ex) { pool.shutdown(); } }}class Handler implements Runnable { private final Socket socket; Handler(Socket socket) { this.socket = socket; } public void run() { // read and service request on socket }}
上面通过Executors.newFixedThreadPool(poolSize)创建线程,通过查看Executors,Executors.newFixedThreadPool(poolSize)调用了:
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
再往里看:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
ok就到这里,线程池中有一个corePoolSize就是在线程池中始终保持的数量,maximumPoolSize就是如果在当前线程池创建的线程都被在占用的时候,可以多创建maximumPoolSize-corePoolSize个线程保证任务执行。如果还是不够的话,未被执行的任务只能等待当前任务执行完成才可以被执行。
3.android里面通过线程池下载图片
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import android.app.Activity;import android.graphics.Bitmap;import android.os.Bundle;import android.os.Handler;import android.widget.ImageView;import cn.sundroid.imageloader.listener.ImageLoaderListener;import cn.sundroid.imageloader.thread.LoadBitmapTask;public class MainActivity extends Activity { private ImageView image; //创建线程池服务 private ExecutorService executorService = Executors.newFixedThreadPool(Thread.NORM_PRIORITY - 2); private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); image = (ImageView) findViewById(R.id.image); handler = new Handler(); LoadBitmapTask task = new LoadBitmapTask(new ImageLoaderListener() { @Override public void onLoadFinished(Bitmap bitmap) { image.setImageBitmap(bitmap); } }, handler); //将任务抛到线程池中执行 executorService.execute(task); }}
之前说过由于必须在主线程中更新UI,所以我们在UI线程中创建了一个Handler并且传到Task中。
import java.io.InputStream;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Handler;import cn.sundroid.imageloader.downloader.ImageDownloader;import cn.sundroid.imageloader.listener.ImageLoaderListener;import cn.sundroid.imageloader.utils.Constants;public class LoadBitmapTask implements Runnable { private ImageLoaderListener listener; private Handler handler; public LoadBitmapTask(ImageLoaderListener listener, Handler handler) { super(); this.listener = listener; this.handler = handler; } @Override public void run() { InputStream is = ImageDownloader.getStream(Constants.image_url0); final Bitmap bitmap = BitmapFactory.decodeStream(is); handler.post(new Runnable() { @Override public void run() { if (listener != null) { listener.onLoadFinished(bitmap); } } }); }}
并且通过handler的post方法执行这个Runnable。
Causes the Runnable r to be added to the message queue.The runnable will be run on the thread to which this handler is attached.
这个解释就不多说了,好了就到这里,执行结果就不贴了和之前的一样。
- 从零开始编写图片加载库(三)之线程池图片下载
- 从零开始编写图片加载库(二)之AsyncTask图片下载
- 从零开始编写图片加载库(一)之Handler+Thread图片下载
- 从零开始编写图片加载库(四)之图片缓存MemoryCache
- 从零开始编写图片加载库(五)之图片缓存DiskCache
- 位图管理、图片下载缓存、管理图片内存 (三) 在非UI线程中处理位图
- Android开发之图片处理专题(三):利用ThreadPoolExcutor线程池实现多图片的异步加载
- AsyncTask加载之图片下载(2)
- 从零开始打造一个新闻订阅APP之Android篇(三、关于图片加载、展示的那些事)
- RxAndroid从零开始学之三(线程调度)
- android异步图片加载三之handler+线程池+消息队列模式+缓存
- android异步图片加载三之handler+线程池+消息队列模式+缓存
- AsyncTask异步加载之图片下载
- Java线程从零开始(三)——进一步认识线程之生命周期
- Unity游戏之网络图片下载与加载
- web前端之html图片操作详解从零开始(三)----img标签
- 从零开始实现图片加载特效之渐变加载、圆角图片
- 图片加载利器之Picasso(三)进阶
- 从零开始编写图片加载库(二)之AsyncTask图片下载
- Userdefault在Mac下Xcode中的存储位置
- vs2010 替换 字符
- 顶级风投资本家对未来科技的10大预测
- ffmpeg configure 不支持 --enable-libopencv 解决
- 从零开始编写图片加载库(三)之线程池图片下载
- Android: Looper, Handler, HandlerThread. Part II
- Android OkHttp完全解析
- 如何做互联网产品分析?
- 客户端发送xml数据,服务器端接收之
- java素数
- 说说EMC解决方案中的那些产品和案例(一)
- Unity3D中用于工具制作常用属性(Attribute)
- android高手进阶教程(一)之--android中的消息机制