Java中的多线程Thread Runnable及android的handler
2015-10-25 12:52
489 查看
1.在java中,多线程一般有两种方式。简言之:一个是继承Thread类,另一个是实现runnable接口。他们之间的区别主要是在于,对于同时开启的多个对象去启动多线程的时候,继承Thread的各个对象之间不能实现数据的共享,而runnable可以。最经典的例子就是买票系统的实现。大家可以百度代码。
android 的多线程实际上就是java的多线程。android的UI线程又称为主线程。
Thread 和 Runnable:
Thread是一个线程,而Runnable可以理解为一个任务。这个任务只是一个接口。具体的任务执行是在 run()方法执行。
Thread thread = new Thread(Runnable);
把一个Runnable任务放到线程里面,当调用thread.start() 的时候,系统新开一个线程去执行,这个runnable任务是在多线程执行的。是在新开的线程执行的。
如果直接 new Runnable().run();那么实际上是直接在UI线程执行了这个任务没有进行一个多线程的操作。
总结:runnable()只是一个任务的抽象,并不是多线程。Thread.start()。才是新开一个多线程。并且在新开的线程执行Thread你们的run()方法。
2.继承和实现都需要重写里面的run方法,该方法就是你子线程运行的逻辑方法,同时new出来的对象也需要运行.start方法。特别要注意的是,实现runnable接口的new 出来的对象之后,其实此时根本没有产生一个多线程,我们仍然需要new Thread(new runnable)对象,然后将实现runnable接口对象作为Thread类一个构造方法的参数传进去。
2.1复制别人的代码。继承Thread类
2.2实现runnable接口
3.handler(和线程,Loop一一对应)。
Handler中分发消息的一些方法
[b] sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)[/b]
post类方法允许你排列一个Runnable对象到主线程队列中
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
3.1handler是android中不同线程之间传递消息的机制。最常用的是用来更新系统的UI,因为UI操作只能在Main线程中执行,所以我们一旦在进行比如联网下载比较耗时的操作时,如果是在主线程中,就会报NRA错误,这对用户体验十分不友好,所以,此时如果我们有个在main线程中的handler对象,然后在子线程中进行耗时操作,结束后通过hangdler通知,再在main中更新就可以了。下面我们从handler的各种方法入手
send:(子线程向绑定handler中的main线程发消息)
首先new handler()对象,重写其handleMessager方法,该handler对象默认是在main中
3.1.1 handler.sendEmptyMessage(int what);该方法是发送空消息,用int型what参数区分不同的消息,同理,有其延迟方法 handler.sendEmptyMessageDelayed(what, delayMillis)。
3.1.2 handler.sendMessage(msg);发送消息msg,msg可以传递任意类型对象,同时其也有延迟方法方法。
post:
3.2.1
线程也即main中的,所以这里最好不要进行一些耗时的操作。同时其也有延时方法,以及去runnable对象方法。可以看到并没有多线程参与。
具体来说,这个函数的工作原理如下:
View.post(Runnable)方法。在post(Runnable action)方法里,View获得当前线程(即UI线程)的Handler,然后将action对象post到Handler里。在Handler里,它将传递过来的action对象包装成一个Message(Message的callback为action),然后将其投入UI线程的消息循环中。在Handler再次处理该Message时,有一条分支(未解释的那条)就是为它所设,直接调用runnable的run方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI。
3.3HandlerThread(是用来产生子线程的,thread子类)
该类可以用来实现main线程中向子线程发送消息,此时最重要的就是在子线程中有一个handler对象以及loop对象(mian中的loop对象自己生成,不需要get)
步骤:
创建一个
HandlerThread handlerThread = new HandlerThread("leochin.com");
handlerThread.start(); //创建HandlerThread后一定要记得start()
获取
Looper looper = handlerThread.getLooper();//获得该子线程的loop对象。
创建Handler,通过Looper初始化
Handler handler = new Handler(looper);//将该子线程中的loop对象绑定到handler中,此时的handler就是该子线程的handler,可以在main中调用发送消息。
通过以上三步我们就成功创建
如果想让
此时可以实现不同线程之间进行消息的传递了。
4.下图为handler在不同线程间消息传递的机制。
4.1首先明确,handler和loop需要有自己对应的线程,如下图,为main线程中
4.2其他线程通过main的handler对象将消息封装并存入main的MessgerQuuen中,通过main的loop对象来进行管理
4.3main的handler通过handleMeeager将消息取出在main中处理
![](http://files.colabug.com/forum/201404/02/181239r2h19922p81y9u72.jpg)
一下代码可以加深对Loop的理解
很多理解都是自己的理解,希望对大家的理解有帮助。
相关链接:http://blog.chinaunix.net/zt/1026/androidhandlerrunnablehand_1026281.shtml
android 的多线程实际上就是java的多线程。android的UI线程又称为主线程。
Thread 和 Runnable:
Thread是一个线程,而Runnable可以理解为一个任务。这个任务只是一个接口。具体的任务执行是在 run()方法执行。
Thread thread = new Thread(Runnable);
把一个Runnable任务放到线程里面,当调用thread.start() 的时候,系统新开一个线程去执行,这个runnable任务是在多线程执行的。是在新开的线程执行的。
如果直接 new Runnable().run();那么实际上是直接在UI线程执行了这个任务没有进行一个多线程的操作。
总结:runnable()只是一个任务的抽象,并不是多线程。Thread.start()。才是新开一个多线程。并且在新开的线程执行Thread你们的run()方法。
2.继承和实现都需要重写里面的run方法,该方法就是你子线程运行的逻辑方法,同时new出来的对象也需要运行.start方法。特别要注意的是,实现runnable接口的new 出来的对象之后,其实此时根本没有产生一个多线程,我们仍然需要new Thread(new runnable)对象,然后将实现runnable接口对象作为Thread类一个构造方法的参数传进去。
2.1复制别人的代码。继承Thread类
<span style="font-size:18px;">package org.thread.demo; class MyThread extends Thread{ private String name; public MyThread(String name) { super(); this.name = name; } public void run(){ for(int i=0;i<10;i++){ System.out.println("线程开始:"+this.name+",i="+i); } } } /* package org.thread.demo; public class ThreadDemo01 { public static void main(String[] args) { MyThread mt1=new MyThread("线程a"); MyThread mt2=new MyThread("线程b"); mt1.run(); mt2.run(); } } *///但是,此时结果很有规律,先第一个对象执行,然后第二个对象执行,并没有相互运行。还是单线程此时 //在JDK的文档中可以发现,一旦调用start()方法,则会通过JVM找到run()方法。下面启动start()方法启动线程: package org.thread.demo; public class ThreadDemo01 { public static void main(String[] args) { MyThread mt1=new MyThread("线程a"); MyThread mt2=new MyThread("线程b"); mt1.start(); mt2.start(); } }; //这样程序可以正常完成交互式运行。那么为啥非要使用start();方法启动多线程呢? //在JDK的安装路径下,src.zip是全部的java源程序,通过此代码找到Thread中的start()方法的定义, </span>
2.2实现runnable接口
<span style="font-size:18px;">public interface Runnable{ public void run(); } 例子: package org.runnable.demo; class MyThread implements Runnable{ private String name; public MyThread(String name) { this.name = name; } public void run(){ for(int i=0;i<100;i++){ System.out.println("线程开始:"+this.name+",i="+i); } } }; </span>但是在使用Runnable定义的子类中没有start()方法,只有Thread类中才有。此时观察Thread类,有一个构造方法:public Thread(Runnable targer)此构造方法接受Runnable的子类实例,也就是说可以通过Thread类来启动Runnable实现的多线程。(start()可以协调系统的资源):
<span style="font-size:18px;">package org.runnable.demo; import org.runnable.demo.MyThread; public class ThreadDemo01 { public static void main(String[] args) { MyThread mt1=new MyThread("线程a"); MyThread mt2=new MyThread("线程b"); new Thread(mt1).start(); new Thread(mt2).start(); } } </span>此时thread对象没有被实现,不要和第一种方式中thread之类搞糊涂了。比较推荐使用后一种方法。
3.handler(和线程,Loop一一对应)。
Handler中分发消息的一些方法
[b] sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)[/b]
post类方法允许你排列一个Runnable对象到主线程队列中
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
3.1handler是android中不同线程之间传递消息的机制。最常用的是用来更新系统的UI,因为UI操作只能在Main线程中执行,所以我们一旦在进行比如联网下载比较耗时的操作时,如果是在主线程中,就会报NRA错误,这对用户体验十分不友好,所以,此时如果我们有个在main线程中的handler对象,然后在子线程中进行耗时操作,结束后通过hangdler通知,再在main中更新就可以了。下面我们从handler的各种方法入手
send:(子线程向绑定handler中的main线程发消息)
首先new handler()对象,重写其handleMessager方法,该handler对象默认是在main中
3.1.1 handler.sendEmptyMessage(int what);该方法是发送空消息,用int型what参数区分不同的消息,同理,有其延迟方法 handler.sendEmptyMessageDelayed(what, delayMillis)。
3.1.2 handler.sendMessage(msg);发送消息msg,msg可以传递任意类型对象,同时其也有延迟方法方法。
<span style="font-size:18px;">public class ChangeTextActivity extends Activity { Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { if (msg.what == 1) { num++; tv.setText(num+""); } } }; TextView tv; int num=0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView)findViewById(R.id.textView1); new Thread() { public void run() { handler.sendEmptyMessage(1); sleep(1000);} }.start(); } } </span>
post:
3.2.1
public class QuesPostActivity extends Activity { ImageView iv; /* * 通过post方法指定要执行的动作 * 如果是通过post方法指定要执行的动作,那么 * Handler对象不需要再重写handleMessage方法 * */ Handler handler = new Handler(); Runnable runnable ; Random ran; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iv = (ImageView)findViewById(R.id.imageView1); ran = new Random(); runnable = new Runnable() { @Override public void run() { int red = ran.nextInt(256); int green = ran.nextInt(256); int blue = ran.nextInt(256); iv.setBackgroundColor(Color.rgb(red, green, blue)); //指定在500毫秒之后,运行当前类对象的run方法 handler.postDelayed(this, 500); } }; /* * 一旦运行到post方法,那么马上执行该参数中的Runnable对象的run方法 * 并且注意:此处的Runnable对象中的run方法内可以调用改变UI的代码 * */ handler.post(runnable); } public void click (View v) { //点击按钮停止颜色的切换 /* * 停止参数指定的runnable对象的run方法的运行 * */ handler.removeCallbacks(runnable); } }该代码和注释比较完整的说明了post的一个用法,首先,post中的关键参数就是一个实现了runnable的子类对象,这里是内部类来实现的,在该之类中run方法中写上逻辑,为什么此时的run方法可以更新UI呢,其实runna接口在没有Thread启动时,还是在当前
线程也即main中的,所以这里最好不要进行一些耗时的操作。同时其也有延时方法,以及去runnable对象方法。可以看到并没有多线程参与。
具体来说,这个函数的工作原理如下:
View.post(Runnable)方法。在post(Runnable action)方法里,View获得当前线程(即UI线程)的Handler,然后将action对象post到Handler里。在Handler里,它将传递过来的action对象包装成一个Message(Message的callback为action),然后将其投入UI线程的消息循环中。在Handler再次处理该Message时,有一条分支(未解释的那条)就是为它所设,直接调用runnable的run方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI。
3.3HandlerThread(是用来产生子线程的,thread子类)
该类可以用来实现main线程中向子线程发送消息,此时最重要的就是在子线程中有一个handler对象以及loop对象(mian中的loop对象自己生成,不需要get)
步骤:
创建一个
HandlerThread,即创建了一个包含Looper的线程。
HandlerThread handlerThread = new HandlerThread("leochin.com");
handlerThread.start(); //创建HandlerThread后一定要记得start()
获取
HandlerThread的Looper
Looper looper = handlerThread.getLooper();//获得该子线程的loop对象。
创建Handler,通过Looper初始化
Handler handler = new Handler(looper);//将该子线程中的loop对象绑定到handler中,此时的handler就是该子线程的handler,可以在main中调用发送消息。
通过以上三步我们就成功创建
HandlerThread。通过handler发送消息,就会在子线程中执行。
如果想让
HandlerThread退出,则需要调用
handlerThread.quit();。
此时可以实现不同线程之间进行消息的传递了。
4.下图为handler在不同线程间消息传递的机制。
4.1首先明确,handler和loop需要有自己对应的线程,如下图,为main线程中
4.2其他线程通过main的handler对象将消息封装并存入main的MessgerQuuen中,通过main的loop对象来进行管理
4.3main的handler通过handleMeeager将消息取出在main中处理
![](http://files.colabug.com/forum/201404/02/181239r2h19922p81y9u72.jpg)
一下代码可以加深对Loop的理解
<span style="font-size:18px;">new Thread() { public void run() { Looper.prepare();//在该子线程中生成其对应的loop对象 handler = new Handler(){ public void handleMessage(android.os.Message msg) { Log.i("=====", "=======子线程1"+Thread.currentThread().getName()); } }; }; Looper.loop();//才能将消息循环起来其作用 }; }.start();</span>
很多理解都是自己的理解,希望对大家的理解有帮助。
相关链接:http://blog.chinaunix.net/zt/1026/androidhandlerrunnablehand_1026281.shtml
相关文章推荐
- Android SDK is missing, out of date, or is missing templates. Please ensure you are using SDK versio
- Android Service进程间双向通信之Messenger(系列4)
- Android Studio快捷键
- Android开发工具类集锦
- Android studio 下使用mob的短信验证码SMSSDK
- Android第三方注解框架Annotations和butterknife
- Android:"Binary XML file line # : Error inflating class"
- Android在如何建立一个WebServer
- Android平台免Root无侵入AOP框架Dexposed使用详解
- Android Handler消息传递机制
- Android开发教程:shape和selector的结合使用
- Android中Activity之间的通信和传值
- Android ProgressBar
- 用淘汰的Android手机来DIY防盗器
- 【转】Caused by: android.os.NetworkOnMainThreadException错误解决办法
- Android之drawable state各个属性详解
- Android-->使用默认样式创建View
- Android屏幕适配全攻略(最权威的官方适配指导)
- AndroidStudio环境下导出APK
- Android开源组件---CircleImageView的使用