android多线程的实现方法

一、单线程模型

 

当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。

在开发Android 应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。

如果在非UI线程中直接操作UI线程,会抛出android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views,这与普通的java程序不同。

由于UI线程负责事件的监听和绘图,因此,必须保证UI线程能够随时响应用户的需求,UI线程里的操作应该向中断事件那样短小,费时的操作(如网络连接)需要另开线程,否则,如果UI线程超过5s没有响应用户请求,会弹出对话框提醒用户终止应用程序。

如果在新开的线程中需要对UI进行设定,就可能违反单线程模型,因此android采用一种复杂的Message Queue机制保证线程间通信。

Message Queue:

Message Queue是一个消息队列,用来存放通过Handler发布的消息。Android在第一次启动程序时会默认会为UI thread创建一个关联的消息队列,可以通过Looper.myQueue()得到当前线程的消息队列,用来管理程序的一些上层组件,activities,broadcast receivers 等等。你可以在自己的子线程中创建Handler与UI thread通讯。 

通过Handler你可以发布或者处理一个消息或者是一个Runnable的实例。每个Handler都会与唯一的一个线程以及该线程的消息队列管理。

Looper扮演着一个Handler和消息队列之间通讯桥梁的角色。程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的Handler,Handler接受到消息后调用handleMessage进行处理。

(以上转自http://www.cnblogs.com/nio-nio/archive/2012/07/23/2604900.html

二、多线程的实现

有以下几种方式:  

1)Activity.runOnUiThread(Runnable)  

2)View.post(Runnable) ;View.postDelay(Runnable , long)  

3)Handler  

4)AsyncTask  

Android是单线程模型,这意味着Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行,所以你单纯的new一个Thread并且start()是不行的,因为这违背了Android的单线程模型。那么如何用好多线程呢?总结一下:  
事件处理的原则:所有可能耗时的操作都放到其他线程去处理。 

 对于第一种方法:

activity.runOnUiThread(new Runnable() {               
            @Override 
            public void run() {  
                // TODO Auto-generated method stub  
            	int i = 30;
            	textView.setText(""+i+" s");
            	}
            }  
        });  
第三种:
package handler.activity;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {
	static final int DOWNSUCCESS = 1;
	static final int DOWNFAIL = 0;
	ProgressDialog dialog = null;

	private Handler myHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			// //执行接收到的通知,更新UI 此时执行的顺序是按照队列进行,即先进先出
			super.handleMessage(msg);
			switch (msg.what) {
			case DOWNSUCCESS:
				dialog.dismiss();
				Toast.makeText(MainActivity.this, "下载成功", Toast.LENGTH_SHORT)
						.show();
				break;

			}
		}

	};
	// *****************************************
	// 主线程Handler负责更新UI,Handler与 Thread通过Message通信
	private Thread myThread = new Thread(new Runnable() {

		@Override
		public void run() {
			// 耗时操作
			SystemClock.sleep(2000);
			Message msg = new Message();
			msg.what = DOWNSUCCESS;
			MainActivity.this.myHandler.sendMessage(msg);

		}

	});

	@Override
	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		Button btn = (Button) this.findViewById(R.id.btn);
		btn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				myThread.start();
				dialog = ProgressDialog.show(MainActivity.this, "",
						"Loading. Please wait...", true);

			}
		});
	}

}

HandlerThread  Looper MessageQueue三者之间的关系 
HandlerThread继承于Thread,所以它本质就是个Thread。与普通Thread的差别就在于,它有个Looper成员变量。
这个Looper其实就是对消息队列以及队列处理逻辑的封装,简单说就是 消息队列+消息循环。

Android中每一个线程都跟着一个Looper,Looper可以帮助线程维护一个消息队列,Looper对象的执行需要初始化Looper.prepare方法,
使用Looper.loop方法启动消息队列管理机制,退出时还要使用Looper.release方法释放资源

 

关于Looper Handler Message的原理 与 线程局部变量 请参考这篇文章

点击打开链接

第四中的实现AsyncTask
package androidthread.acitvity;


import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
 
	private Button btn = null;
	private EditText etaddrss = null;
	private EditText etcontent =null;
	private ProgressBar pb =null;
	private ProgressDialog dialog =null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = (Button) this.findViewById(R.id.btnsend);
        etaddrss = (EditText) this.findViewById(R.id.etaddress);
        etcontent = (EditText) this.findViewById(R.id.etcontent);
 
        btn.setOnClickListener(new OnClickListener() {
     
			@Override
			public void onClick(View arg0) {
			
				   new MyThreads().execute(etaddrss.getText().toString(),etcontent.getText().toString());
				
			}});
     
    }
    
    
    //一般作为内部类使用
    public class MyThreads extends AsyncTask<String,Integer  , String>{

    	int i=0;
    	@Override
    	//这里的参数 与 execute 中的相对应
    	//这个方法不在UI线程(主线程)不能访问UI组件
    	protected String doInBackground(String... arg) {
    		//arg[0]+arg[1];
    	
    		while(i<=100){
    		      //模拟耗时操作
    			   SystemClock.sleep(500);
    			   this.publishProgress(i);
    			   i+=10;
    			
    		}
        
    		return  "发送给"+arg[0]+"内容为"+arg[1]+"邮件已成功发送";
    	}
        @Override    //参数reslut 是doInBackground()的返回值
        protected void onPostExecute(String result) {    
                  Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
                  dialog.dismiss();
                  pb.setVisibility(View.INVISIBLE);
        }
	
		@Override
		protected void onPreExecute() {
			  Toast.makeText(MainActivity.this, "开始发送邮件", Toast.LENGTH_SHORT).show();
			   dialog = ProgressDialog.show(MainActivity.this, "", 
					  "Loading. Please wait...", true);

			  pb =new ProgressBar(MainActivity.this,null,android.R.attr.progressBarStyleHorizontal);
			 
			  LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(200,20);

			  params.setMargins(10, 10, 0, 0);

			  pb.setLayoutParams(params);
			  pb.setMax(100);// 设置最大值  
			  
			  pb.setProgress(0);
			 
			  pb.setVisibility(View.VISIBLE);
			  MainActivity.this.addContentView(pb, params);
			  super.onPreExecute();
		}
		@Override
		protected void onProgressUpdate(Integer... process) {
		   Log.i("process",process[0].intValue() +"");
		   pb.setProgress(process[0].intValue() );
		   super.onProgressUpdate(process);
		} 


    }

}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值