android中的Handler和Runnable
最近在做一个项目,在网络请求时考虑用Handler进行处理,然后就研究了一下Handler和Runnable
首先在看一下java中的Runnable
The Runnable
interface should be implemented by any class whose instances are intended to be executed by a thread. The class must define a method of no arguments called run
.
This interface is designed to provide a common protocol for objects that wish to execute code while they are active. For example, Runnable
is implemented by class Thread
. Being active simply means that a thread has been started and has not yet been stopped.
In addition, Runnable
provides the means for a class to be active while not subclassing Thread
. A class that implements Runnable
can run without subclassing Thread
by instantiating a Thread
instance and passing itself in as the target. In most cases, the Runnable
interface should be used if you are only planning to override the run()
method and no other Thread
methods. This is important because classes should not be subclassed unless the programmer intends on modifying or enhancing the fundamental behavior of the class.
这个官方文档中的描述,看原版文档还是很有好处的,就不翻译了。
在Java中Runnable可以实现资源共享的多线程,网上多拿卖票的例子来讲,但是看上去有点模糊不清,对于这样一个代码
MyRunnable runnable = new MyRunnable; new Thread(runnable,"a").start(); new Thread(runnable,"b").start();
它们之间资源共享到底是怎么个共享呢?
现在我们来看一下例子
public class Main { public static void main(String[] args) { new Main().test(); } void test(){ MyRunnable runnable = new MyRunnable(); new Thread(runnable,"a").start(); new Thread(runnable,"b").start(); } public class MyRunnable implements Runnable{ @Override public void run() { for (int i=0;i<5;i++) { System.out.println(Thread.currentThread().getName() + i); } } } }
执行结果
a0
b0
b1
b2
b3
b4
a1
a2
a3
a4
可以看到这两个线程相互之间并没有影响得都执行了5次
然后在我们的Runnable类里边加一个全局变量
public class Main { public static void main(String[] args) { new Main().test(); } void test(){ MyRunnable runnable = new MyRunnable(); new Thread(runnable,"a").start(); new Thread(runnable,"b").start(); } public class MyRunnable implements Runnable{ int num=0; @Override public void run() { for (int i=0;i<5;i++) { ++num; System.out.println(Thread.currentThread().getName() + i+"--------"+num); } } } }
执行结果
b0--------2
b1--------3
a0--------2
b2--------4
a1--------5
b3--------6
a2--------7
b4--------8
a3--------9
a4--------10
可以发现这个全局变量是在两个线程之间共享的
这说明什么?当一个Runnable对象传递到多个线程执行时,Runnable对象的run()方法会在多个线程中执行,而全局变量是在这些线程中共享的
因此,我们可以通过一个全局变量充当线程锁比如:
public class Main { public static void main(String[] args) { new Main().test(); } void test(){ MyRunnable runnable = new MyRunnable(); new Thread(runnable,"a").start(); new Thread(runnable,"b").start(); } public class MyRunnable implements Runnable{ int num=0; final String string =""; @Override public void run() { synchronized (string){ for (int i=0;i<5;i++) { ++num; System.out.println(Thread.currentThread().getName() + i+"--------"+num); } } } } }
这样的执行结果
a0--------1
a1--------2
a2--------3
a3--------4
a4--------5
b0--------6
b1--------7
b2--------8
b3--------9
b4--------10
这样只有当一个线程中的run()方法执行完之后才会执行另一个
然后把同步锁的地方变一下
public class Main { public static void main(String[] args) { new Main().test(); } void test() { MyRunnable runnable = new MyRunnable(); new Thread(runnable, "a").start(); new Thread(runnable, "b").start(); } public class MyRunnable implements Runnable { int num = 0; final String string = ""; @Override public void run() { for (int i = 0; i < 5; i++) { synchronized (string) { ++num; System.out.println(Thread.currentThread().getName() + i + "--------" + num); } } } } }
执行结果
a0--------1
b0--------2
b1--------3
b2--------4
b3--------5
b4--------6
a1--------7
a2--------8
a3--------9
a4--------10
可以看到,两个线程交替执行,但只有一个线程的
++num; System.out.println(Thread.currentThread().getName() + i + "--------" + num);
执行完之后才会执行另一个线程的,所以全局变量的值是依次增加的。
再来看Android中的Handler的post(Runnale)这个方法
public class MainActivity extends AppCompatActivity { Handler handler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MyRunnable myRunnable = new MyRunnable(); handler.post(myRunnable); } class MyRunnable implements Runnable{ @Override public void run() { for (int i=0;i<5;++i){ System.out.println(Thread.currentThread().getName()+"---"+i); } } } }
可以看到,这个Runnable实在主线程上运行的,因为Handler是在主线程上创建的,与主线程绑定。一些新手可能就会以为这样是新建了一个线程,把耗时操作放里边造成UI卡顿。api说明如下:
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.
那么我们post两个呢,代码修改为
MyRunnable myRunnable = new MyRunnable(); handler.post(myRunnable); handler.post(myRunnable);
那相应的结果
可以看到是依次运行的,这也体现了Handler的消息队列的思想
再改一下
MyRunnable myRunnable = new MyRunnable(); handler.post(myRunnable); handler.post(myRunnable); System.out.println("post finish");
可以看到在post之后并不是立即执行。
那么如何post一个runnable对象到子线程执行呢?这就要将Handler与一个子线程绑定
public class MainActivity extends AppCompatActivity { HandlerThread thread = new HandlerThread("subThread"); Handler handler = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); thread.start(); handler = new Handler(thread.getLooper()); MyRunnable myRunnable = new MyRunnable(); handler.post(myRunnable); System.out.println("post finish"); } class MyRunnable implements Runnable{ @Override public void run() { for (int i=0;i<5;++i){ System.out.println(Thread.currentThread().getName()+"---"+i); } } } }
执行结果:
android中的Handler和Runnable的更多相关文章
- 深入源代码解析Android中的Handler,Message,MessageQueue,Looper
本文主要是对Handler和消息循环的实现原理进行源代码分析.假设不熟悉Handler能够參见博文< Android中Handler的使用>,里面对Android为何以引入Handler机 ...
- Android中使用Handler造成内存泄露的分析和解决
什么是内存泄露?Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引用所指向 ...
- Android中使用Handler造成内存泄露
1.什么是内存泄露? Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引用 ...
- Android中的Handler的机制与用法详解
概述: 很多android初学者对android 中的handler不是很明白,其实Google参考了Windows的消息处理机制, 在Android系统中实现了一套类似的消息处理机制.在下面介绍ha ...
- Android中利用Handler实现消息的分发机制(三)
在第二篇文章<Android中利用Handler实现消息的分发机制(一)>中,我们讲到主线程的Looper是Android系统在启动App的时候,已经帮我们创建好了,而假设在子线程中须要去 ...
- 转:Android中的Handler的机制与用法详解
注:Message类的用法: message的几个参数都可以携带数据,其中arg1与arg2可以携带int类型,what是用户自定义的int型,这样接受者可以了解这个消息的信息. 说明:使用Messa ...
- Android中关于Handler的若干思考
在之前的博文中,讲过一些和Handler有关的知识,例如: Android 多线程----AsyncTask异步任务详解 Android多线程----异步消息处理机制之Handler详解 今天再把Ha ...
- 深入探索Android中的Handler
一.概述 1. 什么是Handler Handler是Android消息机制的上层接口,它为我们封装了许多底层的细节,让我们能够很方便的使用底层的消息机制.Handler的最常见应用场景之一便是通过H ...
- Android中的Handler的具体用法
Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行.Android利用Handler来实现UI线程的更新的. Handler是Android中的消息发送器,其在哪个Activit ...
随机推荐
- Bootstrap 和 LESS
Bootstrap 简介 什么是 Bootstrap? Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的 ...
- UVa1605 - Building for UN(构造法)
UVA - 1605 Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Description ...
- 通过搭建一个精简的C语言开发环境了解一个C程序的执行过程
一.如何搭建一个精简的C语言开发环境 准备:下载TC2.0,并解压,比如说“d:\tc2.0\tc”目录 1.在C盘建立一个目录minic c:\ md minic 2.从解压的目录中将以下文件拷贝到 ...
- iscc2016-好长的字符串
Vm0wd2QyVkhVWGhVYmxKV1YwZDRXRmxVUm5kVlJscHpXa2M1VjFKdGVGWlZNbmhQWVd4YWMxZHViRmROYWxaeVdWZDRZV014WkhG ...
- mapreduce (五) MapReduce实现倒排索引 修改版 combiner是把同一个机器上的多个map的结果先聚合一次
(总感觉上一篇的实现有问题)http://www.cnblogs.com/i80386/p/3444726.html combiner是把同一个机器上的多个map的结果先聚合一次现重新实现一个: 思路 ...
- cf B Very Beautiful Number
题意:给你两个数p和x,然后让你找出一个长度为p的数,把它的最后移到最前面之后得到的数是原来数字的x倍,有很多这样的数取最小. 思路:枚举最后一位,然后就可以推出整个的一个数,然后比较得到的数的第一个 ...
- 【HDOJ】2531 Catch him
简单BFS.就是要把所有的D点当成一个整体考虑(整体移动). /* 2531 */ #include <iostream> #include <queue> #include ...
- java学习之关键字
java语言当中的关键字,之所以存在,是为了告诉编译器如何解释一段有意义的代码段.比如说 /**需求:演示java中关键字存在的含义步骤:用class,public,static,void等说明什么是 ...
- 往github上传demo
一直在github上寻找demo,但怎么传demo上githun呢? http://www.2cto.com/kf/201504/390397.html 首先在github上 new一个reposit ...
- Hierarchy Viewer显示视图性能指标
Hierarchy Viewer默认打开“Tree View”窗口无法显示显示Performance indicators: 但选中根视图再点击按钮“Obtain layout times for t ...