使用java concurrent处理异步加载图片功能

转载: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方法的线程,也叫主线程)退出了,但是线程池中依然有线程运行,因此应用(进程)不会退出。

用Java concurrent编写异步加载图片功能

http://marshal.easymorse.com/archives/3085

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

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

image

这里加载的图片,都是从网上直接获取的。如果用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()方法并没有启动新的线程;

利用handler.post()更新UIhttp://hi.baidu.com/xcmxjge/blog/item/d51d5034d399fd345bb5f52e.html

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();      
                   }      
               }      
          }      
    }   



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值