关于ExecutorService的使用
程序员文章站
2022-03-24 12:37:42
...
ExecutorService: 线程池, 顾名思义是一个调度线程运行的管理池。 我预制了一个场景: 在界面上,有5个图片需要进行异步加载, 我们使用了一个线程池管理类 AsyncImageLoader来控制加载图片的线程个数,如果加载的图片原本已经存在,则从系统中调出已有图片进行加载; 如果图片是首次加载,则通过连接加载图片。
1. 需要加载5个图片的界面:
2. AsyncImageLoader类
3. 对AsyncImageLoader的调用异步加载这5个图片
1. 需要加载5个图片的界面:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="图片区域开始"
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
<ImageView
android:id="@+id/imageView1"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
android:layout_width="wrap_content">
</ImageView>
<ImageView
android:id="@+id/imageView2"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
android:layout_width="wrap_content">
</ImageView>
<ImageView
android:id="@+id/imageView3"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
android:layout_width="wrap_content">
</ImageView>
<ImageView
android:id="@+id/imageView4"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
android:layout_width="wrap_content">
</ImageView>
<ImageView
android:id="@+id/imageView5"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
android:layout_width="wrap_content">
</ImageView>
<TextView
android:text="图片区域结束"
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
2. AsyncImageLoader类
public class AsyncImageLoader {
public Map<String, SoftReference<Drawable>> imageCache = new HashMap<String,SoftReference<Drawable>>();
// 线程池的数量设置:在次,设置同时运行3个线程。
private ExecutorService executorService = Executors.newFixedThreadPool(3);
private final Handler handler = new Handler();
public ExecutorService getExecutorService() {
return executorService;
}
public void setExecutorService(ExecutorService executorService) {
this.executorService = executorService;
}
public Drawable loadDrawable(final String imageUrl, final ImageCallback callback){
// 如果缓存中已经加载过该图片,则调用缓存中的图片加载
if(imageCache.containsKey(imageUrl)){
SoftReference<Drawable> softReference = imageCache.get(imageUrl);
if(softReference.get()!=null){
return softReference.get();
}
}
// 首次加载图片的方法,使用线程池调用加载图片的线程
executorService.submit(new Runnable(){
@Override
public void run() {
try {
// 加载图片
final Drawable drawable = loadImageFromUrl(imageUrl);
// 将图片的加载路径保存到缓存中
imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
// 图片加载完成后, 在界面中显示被加载的图片
handler.post(new Runnable() {
public void run() {
callback.imageLoader(drawable);
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
return null;
}
protected Drawable loadImageFromUrl(String imageUrl){
try {
return Drawable.createFromStream(new URL(imageUrl).openStream(), "image.png");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public interface ImageCallback{
public void imageLoader(Drawable imageDrawable);
}
// 关闭线程池
public void shutdownAndAwaitTermination(ExecutorService pool) {
// 关闭线程池,新的任务就不再运行
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
// 设置一个等待时间,使原来已经存在的任务完成其工作
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
Log.i("test", "i am shutting down...");
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
}catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
Log.e("test","something interrupted happend, and i am shutting down....");
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
}
3. 对AsyncImageLoader的调用异步加载这5个图片
public class BatchDownloadActivity extends Activity {
//需要加载的图片名称
private static final String fileRealName = "我的图片1.gif";
private String url;
private int id;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.batch_download);
String fileName = fileRealName;
String url = "";
try {
url = ToolsUtil.getIpAddress() + URLEncoder.encode(fileRealName,"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// url: http://xx.xx.xx.xx:port/webapp/filename.gif
Log.i("test","url=" + url);
// 调用加载图片方法
loadImage(url, R.id.imageView1);
loadImage(url, R.id.imageView2);
loadImage(url, R.id.imageView3);
loadImage(url,R.id.imageView4);
loadImage(url,R.id.imageView5);
//加载完成后,关闭线程管理池
loader.shutdownAndAwaitTermination(loader.getExecutorService());
}
private AsyncImageLoader loader = new AsyncImageLoader();
private void loadImage(final String url, final int id) {
Drawable cacheImage = loader.loadDrawable(url,new AsyncImageLoader.ImageCallback() {
@Override
public void imageLoader(Drawable imageDrawable) {
((ImageView) findViewById(id)).setImageDrawable(imageDrawable);
Log.i("test", "loading new pic");
}
});
if (cacheImage != null) {
((ImageView) findViewById(id)).setImageDrawable(cacheImage);
Log.i("test", "loading existing pic");
}
}
}