您的位置:首页 > 移动开发 > Android开发

android线程之多线程

2016-04-17 12:35 651 查看
相信大家对于什么是android进程和线程的理论应该都有所了解了,不清楚的可以查看这篇文章

android进程和线程

下面进一步学习,如何实现线程和多线程

什么是单线程,什么是多线程?先看这张图



多线程:它是一组指令的集合,在控制流程语句当中,每一个线程就是一条控制语句,线程与线程之间是可以实现数据共享的,所谓多线程,在某一个时间片段同时有多个任务在一起执行。

线程运行过程中的生命周期



这里不细讲过程

下面才是重点,线程实现的方法,我们先看看java里的线程

java实现线程有两种方式:

■继承Thread类

步骤如下:

1、定义一个普通类去继承Thread类,则表明此类是一个线程类。

语法结构:

public class 类名 extends Thread{}


2、重写父类中的run方法

语法结构:

public void run() {
//线程的执行体
}


3、使用线程

调用start方法来执行线程

语法结构:

线程对象名.start();

■实现Runnable接口

步骤如下

1、定义普通类去实现Runnable接口

语法结构:

public class 类名 implements Runnable{}


2、重写run方法

3、启动线程

-定义自己的线程对象

MyThread myThread = new MyThread();


-定义系统的线程对象,把自己的线程对象作为参数传递到系统的线程对象

Thread thread = new Thread(myThread);


-调用start方法执行:thread.start()

当然这两个方式是有区别和优缺点的

采用继承Thread类方式:

(1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。

(2)缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。

采用实现Runnable接口方式:

(1)优点:线程类只是实现了Runable接口,还可以继承其他的类。在这种方式下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。

(2)缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。

我们再来看看android的线程

Android和Java一样,它支持使用Java里面的Thread类来进行一步任务处理。所以可以轻松地像上面Java的例子一样来使用Android上的线程,

但是在

android进程和线程

文章里说过

Android UI工具包不是线程安全的。所以,你不能从一个工作线程中操作你的用户界面,你必须从用户界面中对用户界面做所有的操作。因此,有简单的规则,以Android的单线程模型:

•不要阻塞用户界面线程

•不访问用户界面线程以外的安卓用户界面工具包

所以android的线程实现方式跟java一样有两种,但是处理方法有区别

下面我们来看看

说到线程不得说Handler,它是线程间通信的桥梁,Handler的细节在这里

android的消息处理机制

我们直接上程序

Handler消息处理机制

public class MyHandler extends Handler{
public void handleMessage(Message msg){
switch(msg.what){
case   1  :
//处理消息,例如更新UI
break;
case   2  :
//处理消息
break;
default : break;
}
}
}


或者可以这样写

Handler mHandler = new Handler(){
public void handleMessage(Message msg){
switch(msg.what){
case   1  :
//处理消息,例如更新UI
break;
case   2  :
//处理消息
break;
default : break;
}
}
}


然后 通过new得到一个对象实例

MyHandler mHandler = new MyHandler();


向消息队列发送消息可以使用下列方法发送

mHandler.sendMessage(message);
mHandler.postDelayed(Runnable r, long delayMillis);
mHandler.sendEmptyMessage(int what);
mHandler.sendMessage(Message msg);
mHandler.sendEmptyMessageAtTime(int what, long uptimeMillis);


然后开始创建线程

方式一:继承Thread类

步骤和java创建差不多,直接上程序

public class MyThread extends Thread{
public void run(){
//消息执行体,创建消息并发送到消息队列就在这里发送,如:
Message message =new Message();//得到一个消息对象
message.what=1;//给消息做标记,当handler获取消息时就知道是那个
message.obj=msg;//需要发送的数据
mHandler.sendMessage(message);//向消息队列里加入消息
}
}


开启线程的方法

MyThread myThread = new MyThread();//new一个线程对象
myThread.start();//使用start()方法启动线程


注意:不一定run()方法里的message都是用上面的方法创建,看情况而定

方式二:实现Runnable接口

直接上程序

public MyRunnable implements Runnable{
public void run(){
//消息执行体,创建消息并发送到消息队列就在这里发送,如:
Message message =new Message();//得到一个消息对象
message.what=1;//给消息做标记,当handler获取消息时就知道是那个
message.obj=msg;//需要发送的数据
mHandler.sendMessage(message);//向消息队列里加入消息
}
}


注意:有时根据需要可以通过写构造函数传入参数

启动线程方法

MyRunnable myRunable = new MyRunnable();//得到一个Runnable对象
Thread thread = new Thread(myRunnable);//new一个thread并传入runnable对象
thread.start();//使用start()方法启动线程


有时候为了看起来紧凑可以这样写

new Thread(new Runnable(){
public void run(){
//消息执行体,创建消息并发送到消息队列就在这里发送,如:
Message message =new Message();//得到一个消息对象
message.what=1;//给消息做标记,当handler获取消息时就知道是那个
message.obj=msg;//需要发送的数据
mHandler.sendMessage(message);//向消息队列里加入消息
}
}).start();


Runnable 并不一定是新开一个线程,比如下面的调用方法就是运行在UI主线程中的:

Handler mHandler=new Handler();
mHandler.post(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
}
});


Runnable是一个接口,不是一个线程,一般线程会实现Runnable。 所以如果我们使用匿名内部类是运行在UI主线程的,如果我们使用实现这个Runnable接口的线程类,则是运行在对应线程的。

这种情况下,由于不是在新的线程中使用,所以千万别做复杂的计算逻辑。

下面给出简单例子(经典的在UI中实现计时操作)

XML布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<LinearLayout
android:id="@+id/my_lay"
android:layout_below="@id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">

<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />

<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:layout_centerHorizontal="true"
android:layout_marginTop="116dp"
android:text="button" />

</LinearLayout>
</RelativeLayout>


主程序

先做个简单的描述:

在这个例子里使用了上面的两种方式来创建线程,一个线程实现计时,一线程往TextView写入信息,Button按键按下计时停止

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
private final int MESSAGE_WHAT_1 = 1;//消息标记
private final int MESSAGE_WHAT_2 = 2;
private final int MESSAGE_WHAT_3 = 3;
public Button btn1 = null;
private TextView tv = null;
private TextView tv1 = null;
private boolean isRunning = true;//计时
private int timer = 0;
public Handler mHandler = null;
private Thread mThread = null;
private Thread mThread1 = null;
private MyRunnable mRunnable = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

tv=(TextView)findViewById(R.id.textView1);
tv1=(TextView)findViewById(R.id.textView2);
btn1=(Button)findViewById(R.id.button1);
btn1.setOnClickListener(new bt1Listener());

mHandler =  new MyHandler();

//线程1
mRunnable = new MyRunnable();
mThread = new Thread(mRunnable);
mThread.start();

//线程2
mThread1 = new MyThread();
mThread1.start();
}
public class MyHandler extends Handler{
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_WHAT_2:
//通过继承Thread类实现的线程更新UI
String str1=msg.getData().getString("text1");
String str2=msg.getData().getString("text2");
tv.setText(str1 + " " + str2);
case MESSAGE_WHAT_1:
//通过实现Runnable来更新UI
tv1.setText("逝去了:" + msg.obj);//经典的更新UI例子。在UI中计时
break;
default: break;
}
}
}

//方法一:继承Thread类
public class MyThread extends Thread{
//private String data = "";
public MyThread(){//通过构造函数来传入数据
super();
}
public void run(){
Message message=new Message();//new一个Message对象
message.what = MESSAGE_WHAT_2;//给消息做标记
Bundle bundle = new Bundle();
bundle.putString("text1","这个继承Thread类");  //往Bundle中存放数据
bundle.putString("text2","来更新UI");  //往Bundle中put数据
message.setData(bundle);//mes利用Bundle传递数据
mHandler.sendMessage(message);//Handler将消息放入消息队列
}
}
//方法二:实现implements接口
public class MyRunnable implements Runnable{
@SuppressWarnings("static-access")
public void run(){
try {

while(isRunning){
Thread.currentThread().sleep(1000);
timer++;//加1计时
Message message = new Message();//new一个message对象
message.obj = timer;//将timer封装到消息里
message.what = MESSAGE_WHAT_1;//做标记
mHandler.sendMessage(message);//加入消息队列
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
class bt1Listener implements OnClickListener{
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
isRunning = false;
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

}


效果图:





点击Button



其实android实现多线程的方法可采用runOnUiThread,post,handle,AsyncTask技术实现。

这里讲解的是使用handler,其他的由大家来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 多线程 线程