今天在论坛上看到一些关于线程的帖子,我觉得与我理解的有些差异,拿上来与大家讨论下
关于android的线程模型:当一个android的应用运行后, 就会有一个UI的main线程启动,这是一个非常重要的线程,它负责把事件分派到相应的控件,其中就包括屏幕绘图事件,它同样是用户与android控件交互的线程。比如,当你在屏幕上的EditText上输入文字,UI线程会把这个事件分发给刚输入文字的EditText,紧接会向事件队列发送一个更新(invalidate)请求。UI线程会把这个请求移出事件队列并通知EditText在屏幕上重新绘制自身。
这种单线线程模型就会使得android的应用程序性能低下, 如果在这个单线程里执行一些耗时的操作, 比如访问数据库, 或是从网络端下载图片, 就会会阻塞整个用户界面。 比如如下操作:
1. Bitmap b = loadImageFromNetwork();
复制代码
这个操作非常耗时, 在这种情况下你会发现, 界面僵死在那里并且android在系统5秒中后没有反应,会显示一个关闭或等待的错误。
也许我们可以使用一个新的Thread来解决它
1. new Thread(new Runnable() {
2. public void run() { Bitmap b = loadImageFromNetwork();
3. mImageView.setImageBitmap( b );
4. }
5. }).start();
复制代码
但这样会发生一些很难察觉的错误, 因为我们知道UI线程不是线程安全的。当然有很多种方法来处理这个问题:
android提供了几种在其他线程中访问UI线程的方法。
• Activity.runOnUiThread( Runnable )
• View.post( Runnable )
• View.postDelayed( Runnable, long )
• Hanlder
1. new Thread( new Runnable() {
2. public void run() {
3. final Bitmap b = loadImageFromNetwork();
4. mImageView.post( new Runnable() {
5. mImageView.setImageBitmap( b );
6. });
7. }
8. }).start();
复制代码
这种方法比较繁琐,同时当你需要实现一些很复杂的操作并需要频繁地更新UI时这会变得更糟糕。为了解决这个问题,android提供了一个工具类:AsyncTask,它使创建需要与用户界面交互的长时间运行的任务变得更简单。
我就拿加载网络图片举个例子:
1. public class CanvasImageTask extends AsyncTask<ImageView, Void, Bitmap>{
2. private ImageView gView ;
3.
4. protected Bitmap doInBackground(ImageView... views) {
5. Bitmap bmp = null ;
6. ImageView view = views[0];
7. // 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。
8. if (view.getTag() != null) {
9. try {
10. URL url = new URL(view.getTag().toString());
11. HttpURLConnection conn = (HttpURLConnection)url.openConnection();
12. conn.setDoInput(true);
13. conn.connect();
14. InputStream stream = conn.getInputStream();
15. bmp = BitmapFactory.decodeStream(stream);
16. stream.close();
17. } catch (Exception e) {
18. Log.v("img", e.getMessage());
19. return null;
20. }
21. }
22. this.gView = view;
23. return bmp;
24. }
25. protected void onPostExecute(Bitmap bm) {
26. if (bm != null) {
27. this.gView.setImageBitmap(bm);
28. this.gView = null ;
29. }
30. }
31.
32. }
复制代码
在Activity中直接调用
1. if(!img.isDrawingCacheEnabled() || !holder.image.getTag().equals(imgpath)){
2. img.setImageResource(R.drawable.icon_app);
3. img.setTag(imgpath);
4. try{
5. new CanvasImageTask().execute(img);
6. img.setDrawingCacheEnabled(true);
7. }catch (Exception e) {
8. Log.e("error", "RejectedExecutionException in content_img: " + imgpath);
9. }
10. }
复制代码
这样图片加载使用异步线程便不会进行堵塞发生错误,我们还可以使用callback在图片加载完后进行回调
1. public class CanvasImageTaskCall extends AsyncTask<ImageView, Void, Bitmap> implements Callback{
2. private ImageView gView ;
3.
4. protected Bitmap doInBackground(ImageView... views) {
5. Bitmap bmp = null ;
6. ImageView view = views[0];
7. // 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。
8. if (view.getTag() != null) {
9. try {
10. URL url = new URL(view.getTag().toString());
11. HttpURLConnection conn = (HttpURLConnection)url.openConnection();
12. conn.setDoInput(true);
13. conn.connect();
14. InputStream stream = conn.getInputStream();
15. bmp = BitmapFactory.decodeStream(stream);
16. stream.close();
17. } catch (Exception e) {
18. e.printStackTrace();
19. Log.v("img", e.getMessage());
20. Message msg = new Message();
21. msg.what = 0;
22. handleMessage(msg);
23. return null;
24. }
25. }
26. this.gView = view;
27. return bmp;
28. }
29. protected void onPostExecute(Bitmap bm) {
30. if (bm != null) {
31. this.gView.setImageBitmap(bm);
32. this.gView.setTag(bm);
33. this.gView = null ;
34. Message msg = new Message();
35. msg.what = 1;
36. handleMessage(msg);
37. }
38. }
39. public boolean handleMessage(Message msg) {
40. // TODO Auto-generated method stub
41. return false;
42. }
43.
44. }
复制代码
在Activity中直接调用
1. new CanvasImageTaskCall(){
2. @Override
3. public boolean handleMessage(Message msg) {
4. switch (msg.what) {
5. case 0:
6. Log.i("test", "图片加载失败");
7. break;
8. case 1:
9. Log.i("test", "图片加载成功");
10. break;
11. default:
12. break;
13. }
14. saveButton.setTextColor(Color.WHITE);
15. saveButton.setClickable(true);
16. bitmap = (Bitmap) imageView.getTag();
17. return super.handleMessage(msg);
18. }
19. }.execute(img);
复制代码
关于android的线程模型:当一个android的应用运行后, 就会有一个UI的main线程启动,这是一个非常重要的线程,它负责把事件分派到相应的控件,其中就包括屏幕绘图事件,它同样是用户与android控件交互的线程。比如,当你在屏幕上的EditText上输入文字,UI线程会把这个事件分发给刚输入文字的EditText,紧接会向事件队列发送一个更新(invalidate)请求。UI线程会把这个请求移出事件队列并通知EditText在屏幕上重新绘制自身。
这种单线线程模型就会使得android的应用程序性能低下, 如果在这个单线程里执行一些耗时的操作, 比如访问数据库, 或是从网络端下载图片, 就会会阻塞整个用户界面。 比如如下操作:
1. Bitmap b = loadImageFromNetwork();
复制代码
这个操作非常耗时, 在这种情况下你会发现, 界面僵死在那里并且android在系统5秒中后没有反应,会显示一个关闭或等待的错误。
也许我们可以使用一个新的Thread来解决它
1. new Thread(new Runnable() {
2. public void run() { Bitmap b = loadImageFromNetwork();
3. mImageView.setImageBitmap( b );
4. }
5. }).start();
复制代码
但这样会发生一些很难察觉的错误, 因为我们知道UI线程不是线程安全的。当然有很多种方法来处理这个问题:
android提供了几种在其他线程中访问UI线程的方法。
• Activity.runOnUiThread( Runnable )
• View.post( Runnable )
• View.postDelayed( Runnable, long )
• Hanlder
1. new Thread( new Runnable() {
2. public void run() {
3. final Bitmap b = loadImageFromNetwork();
4. mImageView.post( new Runnable() {
5. mImageView.setImageBitmap( b );
6. });
7. }
8. }).start();
复制代码
这种方法比较繁琐,同时当你需要实现一些很复杂的操作并需要频繁地更新UI时这会变得更糟糕。为了解决这个问题,android提供了一个工具类:AsyncTask,它使创建需要与用户界面交互的长时间运行的任务变得更简单。
我就拿加载网络图片举个例子:
1. public class CanvasImageTask extends AsyncTask<ImageView, Void, Bitmap>{
2. private ImageView gView ;
3.
4. protected Bitmap doInBackground(ImageView... views) {
5. Bitmap bmp = null ;
6. ImageView view = views[0];
7. // 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。
8. if (view.getTag() != null) {
9. try {
10. URL url = new URL(view.getTag().toString());
11. HttpURLConnection conn = (HttpURLConnection)url.openConnection();
12. conn.setDoInput(true);
13. conn.connect();
14. InputStream stream = conn.getInputStream();
15. bmp = BitmapFactory.decodeStream(stream);
16. stream.close();
17. } catch (Exception e) {
18. Log.v("img", e.getMessage());
19. return null;
20. }
21. }
22. this.gView = view;
23. return bmp;
24. }
25. protected void onPostExecute(Bitmap bm) {
26. if (bm != null) {
27. this.gView.setImageBitmap(bm);
28. this.gView = null ;
29. }
30. }
31.
32. }
复制代码
在Activity中直接调用
1. if(!img.isDrawingCacheEnabled() || !holder.image.getTag().equals(imgpath)){
2. img.setImageResource(R.drawable.icon_app);
3. img.setTag(imgpath);
4. try{
5. new CanvasImageTask().execute(img);
6. img.setDrawingCacheEnabled(true);
7. }catch (Exception e) {
8. Log.e("error", "RejectedExecutionException in content_img: " + imgpath);
9. }
10. }
复制代码
这样图片加载使用异步线程便不会进行堵塞发生错误,我们还可以使用callback在图片加载完后进行回调
1. public class CanvasImageTaskCall extends AsyncTask<ImageView, Void, Bitmap> implements Callback{
2. private ImageView gView ;
3.
4. protected Bitmap doInBackground(ImageView... views) {
5. Bitmap bmp = null ;
6. ImageView view = views[0];
7. // 根据iconUrl获取图片并渲染,iconUrl的url放在了view的tag中。
8. if (view.getTag() != null) {
9. try {
10. URL url = new URL(view.getTag().toString());
11. HttpURLConnection conn = (HttpURLConnection)url.openConnection();
12. conn.setDoInput(true);
13. conn.connect();
14. InputStream stream = conn.getInputStream();
15. bmp = BitmapFactory.decodeStream(stream);
16. stream.close();
17. } catch (Exception e) {
18. e.printStackTrace();
19. Log.v("img", e.getMessage());
20. Message msg = new Message();
21. msg.what = 0;
22. handleMessage(msg);
23. return null;
24. }
25. }
26. this.gView = view;
27. return bmp;
28. }
29. protected void onPostExecute(Bitmap bm) {
30. if (bm != null) {
31. this.gView.setImageBitmap(bm);
32. this.gView.setTag(bm);
33. this.gView = null ;
34. Message msg = new Message();
35. msg.what = 1;
36. handleMessage(msg);
37. }
38. }
39. public boolean handleMessage(Message msg) {
40. // TODO Auto-generated method stub
41. return false;
42. }
43.
44. }
复制代码
在Activity中直接调用
1. new CanvasImageTaskCall(){
2. @Override
3. public boolean handleMessage(Message msg) {
4. switch (msg.what) {
5. case 0:
6. Log.i("test", "图片加载失败");
7. break;
8. case 1:
9. Log.i("test", "图片加载成功");
10. break;
11. default:
12. break;
13. }
14. saveButton.setTextColor(Color.WHITE);
15. saveButton.setClickable(true);
16. bitmap = (Bitmap) imageView.getTag();
17. return super.handleMessage(msg);
18. }
19. }.execute(img);
复制代码
发表评论
-
startActivityForResult 简介
2011-03-29 15:55 1270依次打开Activity A1--A2--A3--A4 这时 ... -
startActivityForResult
2011-03-29 15:49 1129startActivityForResult 方法-- ... -
史上最全的Android的Tab与TabHost讲解
2011-03-28 11:22 1568Tab与TabHost 这就是Tab,而盛放Tab的 ... -
Android对话框
2011-03-25 11:21 1114Android 对话框(Dialog)大全 ... -
PreferenceActivity详解
2011-03-25 11:15 1430为了引入这个概率 首先从需求说起 即:现有某Activity专 ... -
TCP/UDP/HTTP
2011-03-25 11:09 1111先来一个讲TCP、UDP和HTTP ... -
9png
2011-03-25 11:08 1904今天学习了用9png图来优化横屏竖屏的UI,使用sdk自带的工 ... -
Notification
2011-03-25 11:07 923Android系统的状态栏(Status Bar)中有一个创新 ... -
一些技巧
2011-03-25 11:03 7651:查看是否有存储卡插入 String status=Envi ... -
布局像素单位
2011-03-25 11:03 811Android的layout文件中有时候可能会指定具体的单位, ... -
使用ActivityGroup来切换Activity和Layout
2011-03-25 11:02 1113在一个主界面中做Activity切换一般都会用TabActiv ... -
activitygroup
2011-03-25 11:01 1676说说tabhost和activitygroup 最近 ... -
类级框架
2011-03-25 11:00 730类集框架:Collection,Map,Iterator,En ... -
Intent打电话
2011-03-25 11:00 1196intent英文意思是意图,pending表示即将发生或来临的 ... -
Intent Uri
2011-03-25 10:59 1053进入联系人页面 1.Intent intent = new I ... -
Service
2011-03-25 10:59 932一、Service的概念 Service是Android程序中 ... -
Broadcast Receiver
2011-03-25 10:56 1920一、Broadcast Receiver简介 Android中 ... -
ContentProvider MIME类型
2011-03-25 10:55 1229Android程序的主要4部分 ... -
ContentProvider-1查询
2011-03-25 10:55 1215今天看了android的官方文档中ContentProvide ... -
ContentProvider-2modify data:insert,update,delete
2011-03-25 10:54 1184今天补充关于modify data ...
相关推荐
在Windows编程领域,MFC(Microsoft Foundation Classes)是微软提供的一套C++库,用于简化Windows应用程序的开发,包括创建用户界面和实现多线程功能。MFC中的多线程技术使得程序能够同时执行多个任务,提高应用的...
在计算机编程中,多线程是并发执行任务的一种方式,特别是在服务器端开发中,它能够有效地提高系统的资源利用率和响应速度。"多线程之间的线程通信"是确保多个线程协同工作、避免数据不一致性和提高程序效率的关键...
在C#中,由于使用线程和调用UI的线程属于两个不同的线程,如果在线程中直接设置UI元素的属性,此时就会出现跨线程错误。 下面介绍两种解决方案 第一种:使用控件自带的Invoke或者BeginInvoke方法。 Task....
基于SpringBoot和POI实现单线程和多线程导出Excel.zip基于SpringBoot和POI实现单线程和多线程导出Excel.zip基于SpringBoot和POI实现单线程和多线程导出Excel.zip基于SpringBoot和POI实现单线程和多线程导出Excel.zip...
在VC++编程环境中,线程同步是一个至关重要的概念,特别是在多线程程序设计中,以确保并发执行的线程能够安全地访问共享资源,避免数据竞争和其他潜在的问题。本篇文章将详细探讨线程锁在VC++中的应用,以及如何通过...
在计算机编程中,多线程是一种并发执行任务的机制,它可以极大地提高程序的执行效率,尤其是在处理大量数据或需要同时进行多个操作时。本主题主要关注如何在已有的线程中创建子线程,实现更复杂的并发执行模式。 ...
本文将深入探讨如何挂起线程、休眠线程以及终止线程,这些都是多线程编程中的关键概念。 首先,让我们了解线程的基本概念。线程是程序执行的流程,每个进程至少有一个线程。在多线程环境中,多个线程可以共享同一...
"系统线程(内核线程)和用户线程区别" 系统线程(内核线程)和用户线程是两种不同的线程模式,它们在实现和应用方面有很大的区别。 系统线程(内核线程)是由操作系统内核创建和撤销的线程,内核维护进程及线程的...
### MFC多线程的创建详解 #### 一、MFC多线程概述 MFC (Microsoft Foundation Classes) 是微软为简化Windows程序开发提供的一套类库,它封装了Win32 API,使得开发者能够更加方便地进行Windows应用程序的开发。在...
在计算机编程领域,尤其是涉及到实时系统和并发编程时,线程锁和线程安全变量是至关重要的概念。LabWindows/CVI是一种流行的交互式C开发环境,特别适合于开发科学和工程应用。本实例将深入探讨如何在LabWindows/CVI...
单线程和多线程是计算机程序执行时的两种不同模型,它们在处理并发任务、资源管理和性能上有着显著的差异。理解这两种模型是编程尤其是服务器端开发的基础,尤其是在Java、C#等支持多线程的编程语言中。 首先,让...
本文将深入探讨“C#内存释放-线程控制-线程启动-线程暂停”这一主题,结合提供的WFormsThread文件,我们可以假设这是一个关于Windows Forms应用程序中线程管理的实例。 首先,让我们关注线程控制。在C#中,我们通常...
在多线程编程中,线程间的协作是关键任务之一,尤其当需要一个线程在完成特定工作后通知另一个线程继续执行时。这个过程通常涉及到线程同步和异步的概念。本文将深入探讨线程异步工作以及如何在C++中实现一个线程在...
本篇文章将深入探讨如何在MFC中创建多线程,特别是工作者线程,并且会针对`AfxBeginThread`和`BeginThread`两种方法进行比较。 首先,我们来看标题所提到的“MFC创建多线程(工作者线程)demo”。工作者线程通常...
在编程领域,多线程是一种常见且强大的技术,它允许程序同时执行多个任务,从而提高效率和响应性。本主题聚焦于Delphi 7中实现的多线程测试,特别是涉及40个并发线程的情况。Delphi是Embarcadero开发的一款集成开发...
在IT行业中,多线程是程序设计中的一个重要概念,特别是在C#编程中。"大漠多线程模板"是一个专门针对C#开发的多线程处理框架,它为开发者提供了便捷的方式来管理和优化多线程应用。这个框架由知名开发者"大漠"创建,...
在这个项目中,“TCP-接收线程和发送线程”是一个C/C++实现的多线程编程示例,旨在展示如何在服务器端和客户端之间有效地管理数据的接收和发送。以下将详细介绍相关的知识点。 首先,我们要理解TCP的基本原理。TCP...
在.NET框架中,C#语言提供了强大的多线程支持,使得开发者可以充分利用现代多核处理器的优势,实现并行处理和高效能编程。本资源包含六个C#.NET多线程的实例,涵盖了多线程的基本使用到更高级的概念,如线程互斥。...
在编程领域,线程是程序执行的基本单元,特别是在多任务操作系统中。易语言是一种中文编程环境,它提供了方便的线程操作接口。本篇将详细探讨如何在易语言中实现“正确退出线程”这一重要知识点。 首先,理解线程的...
"多线程编程基础知识" 多线程编程是指在一个程序中同时执行多个线程的技术。每个线程都是一个独立的执行路径,拥有自己的程序计数器、寄存器和堆栈空间。多线程编程可以提高程序的执行效率和响应速度,但也增加了...