首页 文章 精选 留言 我的

精选列表

搜索[安全机制],共10012篇文章
优秀的个人博客,低调大师

Java类加载机制总结

加载(Loading) 加载过程是Java的一大特点,类的来源可以多种多样,压缩包、网络字节流、运行时动态计算生成(reflect)等等...这也造就了Java语言强大的动态特性。 java.lang.Class 验证(Verification) 这一过程主要是为了确保Class的字节流中包含的信息符合虚拟机标准,以免造成破坏 文件格式验证 元数据验证 字节码验证,通过数据流和控制流分析确定程序的语义是合法的 符号引用验证,确保解析动作能够正常执行 准备(Preparation) 这一阶段将会为类变量分配内存并设置其初始值,注意此时进行内存分配的仅包括类变量(static修饰),并且初始值通常情况下是数据类型的零值而不是设定值,如下例 public static int val = 123; 复制代码 在这一阶段变量val的赋值是0而不是123,因为此时尚未执行任何Java方法,而对val复制的putstatic指令在初始化阶段后才会执行。 当然也有特殊情况,如下 public static final int val = 123; 复制代码 加上final关键字修饰后,Java编译时会为val生成ConstantValue属性,这时准备阶段就会根据设置将其值设置为123。 解析(Resolution) 此阶段虚拟机将常量池内的符号替换为直接引用,主要包含以下动作: 类或接口的解析 字段解析 类方法解析 接口方法解析 初始化(Initialization) 这时类加载过程的最后一步,这部分开始真正的执行Java代码,也就是说,这个阶段可以由程序员参与。 此阶段其实就是执行类构造器<clinit>()方法的过程。 类加载器 类加载器(Class Loader)是Java虚拟机的一大创举,它将“获取类的二进制字节流”这个过程交给了开发人员自己去实现,只要编写不同的Class Loader,应用程序本身就可以用相应的方式来获取自己需要的类。 类与加载器的关系 对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在虚拟机中的唯一性。 通俗的讲,就是即便同一个Class文件,被不同的类加载器加载之后,得到也不是同一个“类”(equals方法返回false)。 双亲委派模型 从虚拟机角度讲,只有两种类加载器,一种是启动类加载器(Bootstrap ClassLoader),在hotpot上使用C++实现,属于虚拟机的一部分;另一种则是所有其他类的加载器,这些加载器是独立于虚拟机的,由Java语言实现的,从开发者角度看,可以分为以下两类: 扩展类加载器(Extension ClassLoader) 应用程序类加载器(Appliaction ClassLoader) 当然开发人员也可以自己编写类加载器,最终不同的类加载器之间的层次关系如下图所示: 这就是Java中著名的双亲委派模型,它要求除了顶级的BootStrap加载器之外,其他类加载器都必须有父类加载器,工作流程如下: 如果一个类加载器收到了类加载的请求,他首先不会自己去尝试加载这个类,而是将这个请求委派给父类加载器去完成,只有当父加载器反馈自己无法完成加载请求时,子加载器才会自己去尝试加载这个类。 这样做的好处是,Java类随着它的类加载器一起具备了一种带有优先级的层次关系。举个例子,比如java.lang.Object这个类,无论哪个类加载器加载时,最终都会委派给Bootstrap加载器去加载,这就保证了整个系统运行过程中的Object都是同一个类。 否则,如果用户自己编写了一个java.lang.Object类,并放在程序的classpath中,最终系统将会出现多个不同的Object类,整个Java体系就变得一团混乱了。

优秀的个人博客,低调大师

JavaScript执行机制深层剖析

编译阶段 词法分析(Lexing) 这个过程会将由字符组成的字符串分解成(对编程语言来说)有意义的代码块,这些代 码块被称为词法单元(token)。 简单举个例子:c = b - a 转换为 NAME "c" EQUALS NAME "a" MINUS NAME "b" SEMICOLON 语法分析(Parsing) 这个过程是将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法 结构的树。这个树被称为“抽象语法树”(Abstract Syntax Tree,AST)。 AST大概是下面的样子: 生成可执行代码 将 AST 转换为可执行代码的过程称被称为代码生成。 执行阶段 接下来,我们以一个简单例子进行分析。 var a = 2; function bar() { var b = 2; function foo() { var c = 2; } foo(); } bar(); 1. JS引擎创建一个全局对象(Global Object) 这个对象全局只存在一份,它的属性在任何地方都可以访问,它的存在伴随着应用程序的整个生命周期。全局对象在创建时,将Math,String,Date,document 等常用的JS对象作为其属性。由于这个全局对象不能通过名字直接访问,因此还有另外一个属性window,并将window指向了自身,这样就可以通过window访问这个全局对象了。用伪代码模拟全局对象的大体结构如下: //创建一个全局对象 var globalObject = { Math:{}, String:{}, Date:{}, document:{}, //DOM操作 ... window:this //让window属性指向了自身 } 2. JS引擎会创建一个执行环境栈(Execution Context Stack) 栈 提到栈,小伙伴们都知道,栈是一种类似羽毛球筒存储羽毛球的数据结构,采用先进后出,后进先出的特点。 上图中的羽毛球1一定是先放入栈中,然后是羽毛球2,以此类推,而出栈时,一定是羽毛球5先拿出来,然后是羽毛球4,以此类推,这种方式和栈存取数据的方式如出一辙。 堆 堆数据类型类似与书架。书虽然也整齐的存放在书架上,但是我们只要知道书的名字,我们就可以很方便的取出我们想要的书。 好了好了,扯远了。我们接着往下说,在这只需知道执行环境栈是怎样存取数据的就行。 3. 创建全局执行上下文(Execution Context) 到这你可能会问,上下文是个啥玩意? 是啊,上下文是个什么鬼啊? 上下文不是玩意,也不是什么鬼。 执行上下文可以理解为当前代码的执行环境。JS所有代码都会在自己的上下文环境下运行。 说到上下文,你可能会有这样的疑惑:上下文不就是作用域吗? 老铁,我肯定的告诉你,上下文不是作用域。的确,在JS里,这还真是个很难区分的东东。不过现在我还不能马上道出他们的区别,因为作用域的知识,我们还没有涉及,彻底搞懂JavaScript作用域,通过这篇文章,你将彻彻底底了解关于作用域的一切。 那在JS中会有几种执行环境呢? 大概有3种: 全局环境:JavaScript代码运行起来会首先进入该环境 函数环境:当函数被调用执行时,会进入当前函数中执行代码 eval、with(不建议使用,可忽略) 因此在一个JavaScript程序中,必定会产生多个执行上下文。 go on... 4. 全局上下文推入执行环境栈底 5. 代码开始从上往下执行,这里我们暂且不谈标识符处理,当代码执行到bar(),生成bar执行上下文,推入栈中 6. 代码执行到foo(),生成foo执行上下文,推入栈中 7. foo()执行完,foo执行上下文出栈 8. bar()执行完,bar执行上下文出栈 9. 全局上下文执行上下文出栈 我们用图走一下js执行流程,是这样的: 小伙伴们,现在是不是对JS执行流程有了一个整体认识,下面我们来说点更有意思的。 上下文执行细节 我们先看整体了解下 创建阶段 1. 创建变量对象(Variable Object) 创建变量对象,依次经历了以下几个步骤 建立arguments对象。检测当前上下文参数,建立该对对象下的属性及属性值。(这里提一下,函数的参数是按值传递,我知道你是知道的) 检测关键词function函数声明。检测当前上下文中的函数声明,并挂载到变量对象上,其值是函数对象的引用。 检测var变量声明。检测当前上下文中的var声明,并赋值为undefined;如遇到同名var声明的变量,则会默认覆盖;如遇到同名函数声明,则默认忽略,这也就体现了函数声明的优先级要高于var声明。谁的大哥还是得分清的,哈哈。。。 变量提升 看到这,我觉得你对变量提升具体是什么以及如何实现的应该了解的一清二楚了。 是不是呢? 我们来一道题测试下 function foo() { console.log(a); console.log(baz); var a = 'inner'; var baz = 1; function baz() {} } foo(); 第一处是undefined,第二处是[Function: baz],是不是很简单? 下面我用代码简单模拟下上面的过程 function foo() { function baz() {} var a = undefined; console.log(a); a = 'inner'; console.log(baz); } foo(); 变量对象大概是这样的 VO(foo) = { arguments: {}, baz: <foo reference>, // 表示foo的地址引用 a: undefined } 2. 确定作用域链 作用域链是由当前作用域与上层一系列父级作用域组成,作用域的头部永远是当前作用域,尾部永远是全局作用域。作用域链保证了当前上下文对其有权访问的变量的有序访问。 我们先简单了解下,详细的我们会在彻底搞懂JavaScript作用域中谈到。 var a = 1; function foo() { function baz() { console.log( a ); } baz(); } foo(); // 1 上面的对于我们来说很简单,是吧?没错这就是作用域链的应用。 我们简单模拟下 EC(foo) = { VO(foo): {...}, //省略 ScopeChain: [VO(foo), window], this: } EC(baz) = { VO(baz): {...}, //省略 ScopeChain: [VO(baz), VO(foo), window], this: } 3. 确定this指向 谈到this,大家是不是感到很兴奋,平时写代码时,被这家伙整的晕头转向的,这回我们终于可以揭开this的神秘面纱了,搞清楚它在JS到底是怎样的存在,不过客官别着急,我们这里先不介绍this,因为关于this的内容太多了,我们得慢慢去品味它,这里先记住,this是在执行上下文创建阶段确定的。 this传送门 this真是一个淘气鬼 全局上下文 全局上下文有些特殊,其变量对象永远是window,this永远指向window(在浏览器中,Node中不是)。 即 EC(global) = { VO: window, ScopeChain: {}, this: window } 执行阶段 在执行阶段变量对象(Variable Object)变为活动对象(Active Object)。 VO => AO 这样,如果再面试的时候被问到变量对象和活动对象有什么区别,就又可以自如的应答了,他们其实都是同一个对象,只是处于执行上下文的不同生命周期。不过只有处于函数调用栈栈顶的执行上下文中的变量对象,才会变成活动对象。 执行阶段JS引擎会进行变量赋值、函数引用、执行其他代码,执行顺序取决于代码的位置。 我们就聊到这吧。 喝杯茶, 休息一下。 原文发布时间为:2018年04月08日原文作者:张建成(prettyEcho@github)本文来源:掘金 如需转载请联系原作者

优秀的个人博客,低调大师

Android Flutter 内存机制初探

Dart RunTime简介 Flutter Framework使用Dart语言开发,所以App进程中需要一个Dart运行环境(VM),和Android Art一样,Flutter也对Dart源码做了AOT编译,直接将Dart源码编译成了本地字节码,没有了解释执行的过程,提升执行性能。这里重点关注Dart VM内存分配(Allocate)和回收(GC)相关的部分。 和Java显著不同的是Dart的"线程"(Isolate)是不共享内存的,各自的堆(Heap)和栈(Stack)都是隔离的,并且是各自独立GC的,彼此之间通过消息通道来通信。Dart天然不存在数据竞争和变量状态同步的问题,整个Flutter Framework Widget的渲染过程都运行在一个isolate中。 Dart VM将内存管理分为新生代(New Generatio

优秀的个人博客,低调大师

Laravel实践---middleware生效机制

以前的是5.1版本写的。 现在改成5.6版本。 其中遇到的问题,我会在这个laravel专题中一一指出。 第一个问题是路由时 Route::controller不再支持。 于是,我只好弄成Route:get之类的语法来解决。 第二个问题是中间件如何生效。 写middleware时,不能直接返回view了。。要用response. return response()->view('user'); 然后,将这个中间件,弄进kernel.php里面。 protected $routeMiddleware = [ 'auth' => \Illuminate\Auth\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'middleware.xxx' => \App\Http\Middleware\XXXMiddleware::class, ]; 最后,不管是在controller的__construct里,还是在routers/web.php里,加入中间件缩写。 Route::get('/xxx','xxxController@getIndex')->middleware('middleware.xxx')->name('user.xxx'); public function __construct(){ $this->middleware('middleware.xxx'); }

优秀的个人博客,低调大师

Android 的消息机制(1)

在Android主线程启动时,就会执行Looper对象的消息圈(Message Loop)去监视该线程中的消息队列(Message Queue),当Message Queue中有消息,主线程就会取出此消息,然后处理之。注意:此Looper对象和消息队列对象都是此线程专属的,各只有一个,自己线程的Looper只监视自己线程的MQ,而Handler对象可以有多个。 但是我们自己生成的子线程并不会自动建立Looper对象,但是可以创建Looper对象以及一个Message Queue数据结构。 代码: ?[Copy to clipboard] Downloadzuiniuwang.java *MessageQueue.java *com.test * *Function:TODO * *verdateauthor *────────────────────────────────── *2011-3-19Leon * *Copyright(c)2011,TNTAllRightsReserved. */ packagecom.test; importandroid.app.Activity; importandroid.graphics.Color; importandroid.os.Bundle; importandroid.os.Handler; importandroid.os.Looper; importandroid.os.Message; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.LinearLayout; importandroid.widget.TextView; publicclassMessageQueueextendsActivityimplementsOnClickListener{ privatefinalintWC=LinearLayout.LayoutParams.WRAP_CONTENT; privatefinalintFP=LinearLayout.LayoutParams.FILL_PARENT; publicTextViewtv; privateEventHandlermHandler; privateButtonbtn,btn2,btn3; publicvoidonCreate(Bundleicicle){ super.onCreate(icicle); LinearLayoutlayout=newLinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); btn=newButton(this); btn.setId(101); btn.setText("testlooper"); btn.setOnClickListener(this); LinearLayout.LayoutParamsparam= newLinearLayout.LayoutParams(100,50); param.topMargin=10; layout.addView(btn,param); btn2=newButton(this); btn2.setId(102); btn2.setText("exit"); btn2.setOnClickListener(this); layout.addView(btn2,param); tv=newTextView(this); tv.setTextColor(Color.WHITE); tv.setText(""); LinearLayout.LayoutParamsparam2= newLinearLayout.LayoutParams(FP,WC); param2.topMargin=10; layout.addView(tv,param2); setContentView(layout); } publicvoidonClick(Viewv){ switch(v.getId()){ case101: Looperlooper; looper=Looper.myLooper(); mHandler=newEventHandler(looper); //清除整个MessageQueue里的事件,确保不会通知到别人 mHandler.removeMessages(0); Stringobj="Thismymessage!"; //组装成一个Message对象 Messagem=mHandler.obtainMessage(1,1,1,obj); //将Message物件送入MessageQueue里 mHandler.sendMessage(m); break; case102: finish(); break; } } //------------------------------------------------------ classEventHandlerextendsHandler { publicEventHandler(Looperlooper){ super(looper); } @Override publicvoidhandleMessage(Messagemsg){ tv.setText((String)msg.obj); } } } 说明: 在此程序启动时,当前Activity线程(即主线程, main thread)会自动产生一个Looper对象,并且有了一个MessageQueue数据结构。 当按钮点击后,指令:looper = Looper.myLooper(); 就呼叫Looper类别的静态myLooper()函数,以取得目前线程里的Looper对象的引用。 指令:mHandler =newEventHandler(looper); 用于生成一个Handler的子类EventHandler对象,同时指明是和哪个Looper沟通。Activity等对象可以通过EventHandler对象来将消息传放入MessageQueue里,EventHandler对象也扮演消息Listener的角色,可接收Looper对象所送来的讯息。如下图: 指令:Message m = mHandler.obtainMessage(1, 1, 1, obj); 先诞生一个Message对象,并将数据存入这个对象中。指令:mHandler.sendMessage(m);通过mHandler对象而将讯息放入MessageQueue里。此时,Looper对象看到MessageQueue里有讯息m,就将它广播出去,mHandler对象接到此消息时,会呼叫其handleMessage()函数来处理之,于是输出"This my message!"到画面上。 本文转自 最牛傻蛋 51CTO博客,原文链接:http://blog.51cto.com/zuiniuwang/718341,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android 的消息机制(2)

上一节中,是主线程自己发了一个消息到自己的Message Queue中,并把消息从队列中提取出来。那么如何由别的线程发送消息给主线程的Message Queue中呢? 直接看代码~~?[Copy to clipboard]Downloadzuiniuwang.java <spanstyle="font-size:14px">/** *MessageQueue2.java *com.test * *Function:TODO * *verdateauthor *────────────────────────────────── *2011-3-20Leon * *Copyright(c)2011,TNTAllRightsReserved. */ packagecom.test; /** *ClassName:MessageQueue2 *Function:TODOADDFUNCTION *Reason:TODOADDREASON * *@authorLeon *@version *@sinceVer1.1 *@Date2011-3-20 */ importandroid.app.Activity; importandroid.graphics.Color; importandroid.os.Bundle; importandroid.os.Handler; importandroid.os.Looper; importandroid.os.Message; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.LinearLayout; importandroid.widget.TextView; publicclassMessageQueue2extendsActivityimplementsOnClickListener{ privatefinalintWC=LinearLayout.LayoutParams.WRAP_CONTENT; privatefinalintFP=LinearLayout.LayoutParams.FILL_PARENT; publicTextViewtv; privatemyThreadt; privateButtonbtn,btn2,btn3; publicvoidonCreate(Bundleicicle){ super.onCreate(icicle); LinearLayoutlayout=newLinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); btn=newButton(this); btn.setId(101); btn.setText("testlooper"); btn.setOnClickListener(this); LinearLayout.LayoutParamsparam= newLinearLayout.LayoutParams(100,50); param.topMargin=10; layout.addView(btn,param); btn2=newButton(this); btn2.setId(102); btn2.setText("exit"); btn2.setOnClickListener(this); layout.addView(btn2,param); tv=newTextView(this); tv.setTextColor(Color.WHITE); tv.setText(""); LinearLayout.LayoutParamsparam2= newLinearLayout.LayoutParams(FP,WC); param2.topMargin=10; layout.addView(tv,param2); setContentView(layout); } publicvoidonClick(Viewv){ switch(v.getId()){ case101: t=newmyThread(); t.start(); break; case102: finish(); break; } } //------------------------------------------------------ classEHandlerextendsHandler{ publicEHandler(Looperlooper){ super(looper); } @Override publicvoidhandleMessage(Messagemsg){ tv.setText((String)msg.obj); } } //------------------------------------------------------ classmyThreadextendsThread{ privateEHandlermHandler; publicvoidrun(){ LoopermyLooper,mainLooper; //取出本线程中的Looper,当然如果本句话放在主线程中,则会取得主线程的Looper myLooper=Looper.myLooper(); //取出主线程中的Looper mainLooper=Looper.getMainLooper(); Stringobj; if(myLooper==null){ mHandler=newEHandler(mainLooper); obj="currentthreadhasnolooper,thismessageisfromMainthread!"; } else{ mHandler=newEHandler(myLooper); obj="Thisisfromnewthread."; } mHandler.removeMessages(0); Messagem=mHandler.obtainMessage(1,1,1,obj); mHandler.sendMessage(m); } } } 在本程序中Android仍然会自动替主线程建立Message Queue。在点击按钮之后,新生成的子线程中并不会建立Message Queue。所以,新线程中的myLooper值为null,而mainLooper则指向主线程里的Looper对象。于是,执行当到指令: mHandler = new EHandler(mainLooper); 时这个mHandler是属于主线程的。 通过指令:mHandler.sendMessage(m); 便将消息m存入到主线程的Message Queue里。mainLooper看到Message Queue里有讯息,就会自动处理,主线程会自动回调mHandler的handleMessage()函数来处理消息。 本文转自 最牛傻蛋 51CTO博客,原文链接:http://blog.51cto.com/zuiniuwang/718340,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android 的消息机制(4)

上面的文章我们演示了如何把一个Message由子线程发送给主线程,但是如何将一个Message从主线程发送给子线程呢?子线程在默认的情况下是没有Looper的,也就没有可能操作子线程的消息队列。我们通过查API文档可以看到: Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped. Most interaction with a message loop is through the Handler class. 大概意思是,线程在默认情况下是没有Looper的,但是可以通过调用Prepare()方法来运行一个loop,然后使用loop()方法来处理消息直到loop结束。通常的使用方式是: ?[Copy to clipboard] Downloadzuiniuwang.java classLooperThreadextendsThread{ publicHandlermHandler; publicvoidrun(){ Looper.prepare(); mHandler=newHandler(){ publicvoidhandleMessage(Messagemsg){//processincoming //messageshere } }; Looper.loop(); } } 例程如下,基本过程是这样的,启动主线程,然后启动子线程,子线程注册Looper,主线程发送一个Message给子线程,然后子线程的handler处理此消息,再把此消息发送给主线程的消息队列,主线程空间显示此消息~ ?[Copy to clipboard] Downloadzuiniuwang.java /** *MessageExample4.java *com.test.Message * *Function:TODO * *verdateauthor *────────────────────────────────── *2011-3-23Leon * *Copyright(c)2011,TNTAllRightsReserved. */ packagecom.test.Message; importandroid.app.Activity; importandroid.graphics.Color; importandroid.os.Bundle; importandroid.os.Handler; importandroid.os.Looper; importandroid.os.Message; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.LinearLayout; importandroid.widget.TextView; /** *ClassName:MessageExample4主线程如何传递消息给子线程Function:TODOADDFUNCTIONReason: *TODOADDREASON * *@authorLeon *@version *@sinceVer1.1 *@Date2011-3-23 */ publicclassMessageExample4extendsActivityimplementsOnClickListener{ privatefinalintWC=LinearLayout.LayoutParams.WRAP_CONTENT; privatefinalintFP=LinearLayout.LayoutParams.FILL_PARENT; publicTextViewtv; privateButtonbtn,btn2; privateHandlerh; publicvoidonCreate(Bundleicicle){ super.onCreate(icicle); LinearLayoutlayout=newLinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); btn=newButton(this); btn.setId(101); btn.setText("testlooper"); btn.setOnClickListener(this); LinearLayout.LayoutParamsparam=newLinearLayout.LayoutParams(100,50); param.topMargin=10; layout.addView(btn,param); btn2=newButton(this); btn2.setId(102); btn2.setText("exit"); btn2.setOnClickListener(this); layout.addView(btn2,param); tv=newTextView(this); tv.setTextColor(Color.WHITE); tv.setText(""); LinearLayout.LayoutParamsparam2=newLinearLayout.LayoutParams(FP,WC); param2.topMargin=10; layout.addView(tv,param2); setContentView(layout); //启动子线程 newmyThread().start(); } publicvoidonClick(Viewv){ switch(v.getId()){ case101: Stringobj="mainThread"; Messagem=h.obtainMessage(1,1,1,obj); h.sendMessage(m); break; case102: finish(); break; } } //------------------------------------------------------ classEHandlerextendsHandler{ publicEHandler(Looperlooper){ super(looper); } @Override publicvoidhandleMessage(Messagemsg){ tv.setText((String)msg.obj); } } //------------------------------------------------------ classmyThreadextendsThread{ privateEHandlermHandler; publicvoidrun(){ Looper.prepare(); h=newHandler(){ publicvoidhandleMessage(Messagemsg){ EHandlerha=newEHandler(Looper.getMainLooper()); Stringobj=(String)msg.obj+",myThread"; Messagem=ha.obtainMessage(1,1,1,obj); ha.sendMessage(m); } }; Looper.loop(); } } } 本文转自 最牛傻蛋 51CTO博客,原文链接:http://blog.51cto.com/zuiniuwang/718336,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android 的消息机制(3)

当然我们也可以隐式的指定Looper ,代码如下: ?[Copy to clipboard] Downloadzuiniuwang.java /** *MessageQueue2.java *com.test * *Function:TODO * *verdateauthor *────────────────────────────────── *2011-3-20Leon * *Copyright(c)2011,TNTAllRightsReserved. */ packagecom.test.messagequeue; /** *ClassName:MessageQueue2 *Function:TODOADDFUNCTION *Reason:TODOADDREASON * *@authorLeon *@version *@sinceVer1.1 *@Date2011-3-20 */ importandroid.app.Activity; importandroid.graphics.Color; importandroid.os.Bundle; importandroid.os.Handler; importandroid.os.Looper; importandroid.os.Message; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.LinearLayout; importandroid.widget.TextView; publicclassMessageQueue3extendsActivityimplementsOnClickListener{ privatefinalintWC=LinearLayout.LayoutParams.WRAP_CONTENT; privatefinalintFP=LinearLayout.LayoutParams.FILL_PARENT; publicTextViewtv; privatemyThreadt; privateButtonbtn,btn2,btn3; privateEHandlermHandler; publicvoidonCreate(Bundleicicle){ super.onCreate(icicle); LinearLayoutlayout=newLinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); btn=newButton(this); btn.setId(101); btn.setText("testlooper"); btn.setOnClickListener(this); LinearLayout.LayoutParamsparam= newLinearLayout.LayoutParams(100,50); param.topMargin=10; layout.addView(btn,param); btn2=newButton(this); btn2.setId(102); btn2.setText("exit"); btn2.setOnClickListener(this); layout.addView(btn2,param); tv=newTextView(this); tv.setTextColor(Color.WHITE); tv.setText(""); LinearLayout.LayoutParamsparam2= newLinearLayout.LayoutParams(FP,WC); param2.topMargin=10; layout.addView(tv,param2); setContentView(layout); } publicvoidonClick(Viewv){ switch(v.getId()){ case101: //mHandler=newEHandler(Looper.myLooper()); //可以隐式的制定Looper,和上面的效果是一样的 mHandler=newEHandler(); t=newmyThread(); t.start(); break; case102: finish(); break; } } //------------------------------------------------------ classEHandlerextendsHandler{ publicEHandler(Looperlooper){ super(looper); } publicEHandler(){ } @Override publicvoidhandleMessage(Messagemsg){ tv.setText((String)msg.obj); } } //------------------------------------------------------ classmyThreadextendsThread{ publicvoidrun(){ Stringobj="Thismessageisfromnewthread."; mHandler.removeMessages(0); Messagem=mHandler.obtainMessage(1,1,1,obj); mHandler.sendMessage(m); } } 在此代码中,指令:h = new EventHandler();就等于:h = new EventHandler(Looper.myLooper()); 它建立了当前线程(Current Thread)的EventHandler对象。由于是由main线程执行此指令的,所以此EventHandler对象是用来存取main线程的Message Queue的。 本文转自 最牛傻蛋 51CTO博客,原文链接:http://blog.51cto.com/zuiniuwang/718338,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册