转载:http://marshal.easymorse.com/archives/3081

java5开始,增加了concurrent api,用于并发处理。比如起多个线程并发从网络上下载图片,然后在本地显示。

这里写个简单的代码,来说明如何使用concurrent api提供的线程连接池。

运行结果类似这样:

start do 1 task …

>>main thread end.

start do 2 task …

start do 1 finished.

start do 3 task …

start do 2 finished.

start do 3 finished.

这里的task1到task3,都做的同样的事情,让它所属的线程休眠2000ms:

private static void doSomething(int id) {

System.out.println("start do " + id + " task …");

try {

Thread.sleep(1000 * 2);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("start do " + id + " finished.");

}

如果没有java自带的这个api,需要自己或者使用不标准的第三方线程池api。用concurrent api写起来很简洁:

public static void main(String[] args) {

ExecutorService executorService = Executors.newFixedThreadPool(2);

executorService.submit(new Runnable() {

@Override

public void run() {

doSomething(1);

}

});

executorService.submit(new Runnable() {

@Override

public void run() {

doSomething(2);

}

});

executorService.submit(new Runnable() {

@Override

public void run() {

doSomething(3);

}

});

executorService.shutdown();

System.out.println(">>main thread end.");

}

首先,创建了一个线程池,里面有2个线程:

ExecutorService executorService = Executors.newFixedThreadPool(2);

然后,通过submit()方法,提交一个Runnable的实例,这个实例将交由线程池中空闲的线程执行。

在main线程中直接运行了:

executorService.shutdown();

不必担心,线程池不会直接关闭的,只有当它执行完所有提交的任务后才会关闭。如果不写这行,在本例中,应用将不会停止,因为虽然main线程(就是运行main方法的线程,也叫主线程)退出了,但是线程池中依然有线程运行,因此应用(进程)不会退出。

在android异步加载ListView中的图片中使用异步方式加载的图片,当时要的急,写的很粗糙,是为每个图片加载一个线程来实现的。

可以用java concurrent很简明的实现类似功能,并且用到线程池。

这里加载的图片,都是从网上直接获取的。如果用android的UI线程,则需要图片全部加载后才能显示界面。

这里使用了concurrent api通过后台线程并发获取,本例中线程池中只有一个线程,可以设置为多个以加快加载速度。可参见使用java concurrent处理并发需求中的简单示例了解concurrent

api的基本机制。

public class LazyLoadImageActivity extends Activity {

private ExecutorService executorService = Executors.newFixedThreadPool(1);

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

loadImage("http://www.chinatelecom.com.cn/images/logo_new.gif", R.id.image1);

loadImage("http://www.baidu.com/img/baidu_logo.gif", R.id.image2);

loadImage("http://cache.soso.com/30d/img/web/logo.gif", R.id.image3);

}

@Override

protected void onDestroy() {

executorService.shutdown();

super.onDestroy();

}

private void loadImage(final String url, final int id) {

final Handler handler=new Handler();

executorService.submit(new Runnable() {

@Override

public void run() {

try {

final Drawable drawable = Drawable.createFromStream(

new URL(url).openStream(), "image.png");

handler.post(new Runnable() {

@Override

public void run() {

((ImageView) LazyLoadImageActivity.this

.findViewById(id))

.setImageDrawable(drawable);

}

});

} catch (Exception e) {

throw new RuntimeException(e);

}

}

});

}

}

备注:

handler.post(new Runnable() {

@Override

public void run() {

((ImageView) LazyLoadImageActivity.this

.findViewById(id))

.setImageDrawable(drawable);

}

});API中的解释:

boolean android.os.Handler.post(Runnable r)

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.

Parameters:

r The Runnable that will be executed.

Returns:

Returns true if the Runnable was successfully placed in to the message queue. Returns false on failure, usually because the looper processing the message queue is exiting.

这是android提供的一种机制,handler对象将通过post方法,将里面的Runnable对象放到UI执行队列中,UI消费这个队列,调用Runnable的run方法。这里并不生成新的线程。

Android中通过Handler对象的post()方法将一个线程加入线程队列的时候,直接调用了Runnable的run()方法,并没有调用start()方法;也就是说Run()方法所执行的内容还是在

主线程中进行,post()方法并没有启动新的线程;

1.创建一个Handler 2.调用Handler.post(Runnable r)方法3.Runnable运行在UI所在线程,所以可以直接调用View.invalidate()

public class TestHandler extends Activity {

private MyView myView;

private Handler mHandler;

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

myView = new MyView(this);

//创建一个Handler

mHandler = new Handler();

//调用Handler.post(Runnable r)方法

mHandler.post(new Runnable(){

@Override

public void run() {

//直接调用View.invalidate(),更新组件

myView.invalidate();

//延迟5毫秒后执行线程

mHandler.postDelayed(this, 5);

}

});

setContentView(myView);

}

class MyView extends View{

private float x = 0f;

public MyView(Context context) {

super(context);

}

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

x+=1;

Paint mPaint = new Paint();

mPaint.setColor(Color.BLUE);

canvas.drawRect(x, 40, x+40, 80, mPaint);

}

}

}

在新线程里更新UI,可以直接postInvalidate() ,不需要转到UI线程再进行刷新

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

this.requestWindowFeature(Window.FEATURE_NO_TITLE);

myView = new MyView(this);

this.setContentView(this.myView);

new Thread(new myThread()).start();

}

class myThread implements Runnable {

public void run() {

while (!Thread.currentThread().isInterrupted()) {

try {

myView.postInvalidate();

Thread.sleep(100);

} catch (InterruptedException e) {

Thread.currentThread().interrupt();

}

}

}

}

分享到:

2011-12-27 14:04

浏览 259

评论

java图片异步加载_使用java concurrent处理异步加载图片功能相关推荐

  1. 【源码+图片素材】Java王者荣耀游戏开发_开发Java游戏项目【王者荣耀】1天搞定!!!腾讯游戏_Java课程设计_Java实战项目_Java初级项目

    王者荣耀是当下热门手游之一,小伙伴们是否想过如何制作一款属于自己的王者荣耀游戏呢? 本课程讲解了一个王者荣耀游戏的详细编写流程,即使你是刚入门Java的新手,只要你简单掌握了该游戏所需要的JavaSE ...

  2. java类如何加载_简述Java类加载方式及流程

    在学习反射那一章节时想到自己之前学过的知识,故整理一番,希望能提供一点帮助,水平有限,如若有误欢迎指正. Java提供了两种类的装载方式.一是预先加载,二是按需加载.因为可以对类进行按需加载,所以程序 ...

  3. java 多态判断非空_收藏Java 面试题全梳理

    脚本之家 你与百万开发者在一起 来源 | Java建设者(ID:javajianshe) 作者 |cxuan 如若转载请联系原公众号 Java 基础篇 Java 有哪些特点 并发性的:你可以在其中执行 ...

  4. 为啥JAVA虚拟机不开发系统_理解Java虚拟机体系结构

    1 概述 众所周知,Java支持平台无关性.安全性和网络移动性.而Java平台由Java虚拟机和Java核心类所构成,它为纯Java程序提供了统一的编程接口,而不管下层操作系统是什么.正是得益于Jav ...

  5. java对象流保存表格_使用java对象

    <21天学通Java(第7版)>-- 1.3 对象和类 本节书摘来异步社区<21天学通Java(第7版)>一书中的第1章,第1.3节,作者: [美]Rogers Cadenhe ...

  6. java计分系统编程代码_使用Java代码对实时系统进行编程

    由于许多重要原因,Java语言在实时系统中的使用并不广泛. 这些包括Java语言设计固有的不确定性性能影响,例如动态类加载,以及Java Runtime Environment(JRE)本身,例如垃圾 ...

  7. java jsp取静态常量_获取java静态

    Android NDK开发系列教程4:对类变量进行操作 终于建了一个自己个人小站:https://huangtianyu.gitee.io,以后优先更新小站博客,欢迎进站,O(∩_∩)O~~ 通常我们 ...

  8. java url路径包含中文_谈谈 Java 类加载机制

    概述 类加载器主要分为两类,一类是 JDK 默认提供的,一类是用户自定义的. JDK 默认提供三种类加载器: Bootstrap ClassLoader 启动类加载器:每次执行 java 命令时都会使 ...

  9. java字符串拆分成数组_用Java实现JVM第八章《数组和字符串》

    小傅哥 | https://bugstack.cn 沉淀.分享.成长,专注于原创专题案例,以最易学习编程的方式分享知识,让自己和他人都能有所收获.目前已完成的专题有:Netty4.x实战专题案例.用J ...

最新文章

  1. 字节一面:如何从 100 亿 URL 中找出相同的 URL?
  2. 《12个球问题》分析
  3. 8、clone使用和数组列表的copy
  4. (原创) 电源滤波为何要用几个不同量级的电容并联?
  5. 云服务器有i5的性能吗,i5云服务器
  6. dubbo简易监控中心安装
  7. JSF Spring Hibernate集成示例教程
  8. Java多线程--对象的可见性
  9. 虚拟机下挂载CentOS 镜像并配置yum本地镜像源
  10. 增值税防伪税控系统到底是什么呢?
  11. [量化-038]python代码-根据roe估算公司的pb值
  12. 转叶寒栋分享:方舟支持C语言编译新功能开源啦!
  13. 神经网络 高维空间的理解
  14. qcustomplot圆_Qt之QCustomPlot(图形库)
  15. MAXON宣布任命高级领导人员
  16. 【科学有故事】做节目时的Python分析
  17. css浮动,清除浮动,溢出属性,定位,设置透明度
  18. CSS如何使用伪元素选择器给所有的div里的文本前面添加小写罗马数字编号
  19. Android矢量图的制作
  20. error: undefined reference to ‘typeinfo for android::RefBase‘ hidl_death_recipient

热门文章

  1. 从中国移动走出去的咪咕能成功吗?
  2. 机器学习降维算法六——ISOMAP(等距特征映射)
  3. android开源torrent解析,Android之Bt框架
  4. NeatUpload Vs .NetFromWork4.0 配置
  5. CSS Fonts字体属性
  6. 北大本科转行计算机,北京教委公布本科跨省转学名单,两学霸为学计算机转出北大...
  7. 怎么做一个微信自动回复的智能聊天机器人?
  8. 深富策略:盐湖股份大涨吸金 市场风格出现转变!
  9. 以太坊区块链的区块(Block)结构
  10. 5. 每天的领导和合伙人