首页 文章 精选 留言 我的

精选列表

搜索[Android],共10000篇文章
优秀的个人博客,低调大师

Android应用开发提高系列(2)——《Practical Java 中文版》读书笔记(下)

正文 注意:条目和用语可能与书籍有所出入,但尽量保持原样加一些自己的理解。 一、性能 1. 先把焦点放在设计、数据结构和算法身上 备注:良好的设计、明智的选择数据结构和算法可能比高效代码更重要。 2. 不要依赖编译器优化技术 3. 理解运行时(runtime)代码优化 备注:JIT将bytecode于运行时转换为本地二进制码,从而提高性能。因此编译后代码被执行次数越多,本机代码生成代价就很合算。 4. 连接字符串使用StringBuffer要比String快,尤其是大量字符串拼接 5. 将对象创建成本降至最小 备注:复用既有对象,不要创建非必要的对象,只在需要的时候才创建它们。 6. 将同步化(synchronization)降至最低 备注:如果synchronized函数抛出异常,则在异常离开函数之前,锁会自动释放。如果整个函数都需要被同步化,为了产生体积较小且执行速度较快的代码,请优先使用函数修饰符,而不是在函数内使用synchronized代码块。 7. 尽可能使用stack变量 备注:如果在函数中频繁访问成员变量、静态变量,可以用本地(local)变量替代,最后操作完后再赋值给成员/静态变量。 8. 尽可能的使用static、final和private函数 备注:此类函数可以在编译期间被静态决议(statically resolved),而不需要动态议决(dynamic resolved)。(子类无法覆写) 9. 类的成员变量、静态变量都有缺省值,务须重复初始化 备注:记住,本地变量没有缺省值(例如函数内定义的变量)。 10. 尽可能的使用基本数据类型 备注:如int、short、char、boolean,使得代码更快更小。 11. 不要使用枚举器(Enumeration)和迭代器(Iterator)来遍历Vector 备注:使用for循环+get() 12. 使用System.arraycopy()来复制数组 备注:使用System.arraycopy()代替for循环,可以产生更快的代码。如: public voidcopyArray( int[]src, int[]dest){ intsize=src.length; System.arraycopy(src,0,dest,0,size); } System.arraycopy()是以native method实现的,可以直接、高效的移动原始数组到目标数组,因此它执行速度更快。 13. 优先使用数组,然后才考虑Vector和ArrayList,理由: a). Vector的get()是同步的 b). ArrayList基本上就是一个非线程同步的Vector,比Vector要快 c). ArrayList和Vector添加元素或移除元素都需要重新整理数组。 备注:不要仅仅因为手上有个数不定的数据需要存储,就毫无选择的使用Vector或ArrayList。可以考虑创建一个足够大的数组,通常这样可能会浪费内存,但性能上的收益可能超过内存方面的代价。 14. 手工优化代码 a). 剔除空白函数和无用代码 b). 削减强度 备注:以更高效的操作替换成本昂贵的操作。一个常见的优化手法是使用复式复制操作符(如+=、-=)。 c). 合并常量 备注:将变量声明为final,使得操作在编译器就进行。 d). 删减相同的子表达式 备注:可用一个临时变量代替重复的表达式。 e). 展开循环 备注:如循环次数少且已知循环次数,可展开去掉循环结构,直接访问数组元素。缺点是会产生更多代码。 f). 简化代数 备注:使用数学技巧来简化表达式。(例如从1+..+100的问题) g). 搬移循环内的不变式 备注:循环内不变化的表达式可用移至循环外,不必重复计算表达式。 15. 编译为本机代码 备注:将程序的某部分编译为本机二进制代码,然后通过JNI访问。 二、多线程 1. 对于实例(instance)函数,同步机制锁定的是对象,而不是函数和代码块。 备注:函数或代码块被声明为synchronized并非意味它在同一时刻只能有一个线程执行(同一对象不同线程调用会阻塞)。Java语言不允许将构造函数声明为synchronized。 2. 同步实例函数和同步静态函数争取的是不同的locks。 备注:两者均非多线程安全,可以使用实例变量进行同步控制,如(byte[] lock = new byte[0]),比其他任何对象都经济。 3. 对于synchronized函数中可被修改的数据,应使之成为private,并根据需要提供访问函数。如果访问函数返回的是可变对象,那么可以先克隆该对象。 4. 避免无谓的同步控制 备注:过度的同步控制可能导致代码死锁或执行缓慢。再次提醒,当一个函数声明为synchronized,所获得的lock是隶属于调用此函数的那个对象。 5. 访问共享变量时请使用synchronized或volatile 备注:如果并发性很重要,而且不需要更新很多变量,则可以考虑使用volatile。一旦变量被声明为volatile,在每次访问它们时,它们就与主内存进行一致化。如果使用synchronized,只在取得lock和释放lock时候才一致化。 6. 在单一操作(single operation)中锁定所有用到的对象 备注:如果某个同步函数调用了某个非同步实例函数来修改对象,它是线程安全的。使用同步控制时,一定要对关键字synchronized所作所为牢记在心。它锁定的是对象而非函数或代码。 7. 以固定而全局性的顺序取得多个locks(机制)以避免死锁。P/181~P/185 备注:嵌入[锁定顺序]需要额外的一些工作、内存和执行时间。 8. 优先使用notifyAll()而非notify() 备注:notify()和notifyAll()用以唤醒处以等待状态的线程,waite()则让线程进入等待状态。notify()仅仅唤醒一个线程。 9. 针对wait()和notifyAll()使用旋转锁(spin locks) 备注:旋转锁模式(spin-lock pattern)简洁、廉价,而且能确保等待着某个条件变量的代码能循规蹈矩。 10. 使用wait()和notifyAll()替代轮询(polling loops) 备注:调用wait()时会释放同步对象锁,暂停(虚悬,suspend)此线程。被暂停的线程不会占用CPU时间,直到被唤醒。如: public voidrun() { intdata; while( true){ synchronized(pipe){ while((data=pipe.getDate())==0){ try{ pipe.waite(); } catch(InterruptedExceptione){} } } // ProcessData } } 11. 不要对已锁定对象的对象引用重新赋值。 12. 不要调用stop()和suspend() 备注:stop()中止一个线程时,会释放线程持有的所有locks,有搅乱内部数据的风险;suspend()暂时悬挂起一个线程,但不会释放持有的locks,可能带来死锁的风险。两种都会引发不可预测的行为和不正确的行为。 当线程的run()结束时,线程就中止了运行。可以用轮询+变量来控制,如下代码: private volatile booleanstop; public voidstopThread() { stop= true; } public voidrun() { while(!stop){ // ProcessData } } 注意:这里使用了关键字volatile,由于Java允许线程在其 私有专用内存 中保留主内存变量的副本(可以优化),线程1对线程2调用了stopThread(),但线程2可能不会及时察觉到stop主内存变量已变化,导致不能及时中止线程。 三、类与接口 1. 实现一个final类(immutable class 不可变类)时,请遵循下列规则: a). 声明所有数据为private b). 只提供取值函数(getter),不提供赋值函数(setter) c). 在构造函数中设置有实例数据 d). 如果函数返回、接受引用final对象,请克隆这个对象。 e). 区别浅层拷贝和深层拷贝应用场景。如拷贝Vector需要使用深层拷贝。 2. 实现clone()时记得调用super.clone() 备注:不管是浅层拷贝还是深层拷贝都需要调用super.clone()。 3. 别只依赖finalize()清理内存以外的资源 备注:finalize()函数只有在垃圾回收器释放对象占用的空间之前才会被调用,回收时可能并非所有符合回收条件的对象都被回收,也无法保证是否被调用、何时调用。实现finalize()方法时记得调用super.finalize()。 4. 在构造函数内应避免调用非final函数,以免被覆写而改变初衷。 结束 书是从朋友那边借过来的,拿到手也有一段时间,磨磨唧唧好多天才看了几十页,而余下部分从上篇文章到这篇文章也不过才3-5天。发现以这种方式来看书也不错,一方面能加快速度,一方面由于要写文章更加认真细读,还能提炼把书读薄记录分享出来,实在是很适合我这样的 :) 本文转自over140 51CTO博客,原文链接:http://blog.51cto.com/over140/844924,如需转载请自行联系原作者

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

Android:线程间通讯的其他方法、runOnUiThread(action)、Handler.post(action)、post

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 public class MainActivity extends Activity implements OnClickListener { TextViewtextView= null ; private ViewmProgress; private HandlermHandler= new Handler(); @Override protected void onCreate(BundlesavedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.button1).setOnClickListener( this ); findViewById(R.id.button2).setOnClickListener( this ); textView=(TextView)findViewById(R.id.textView1); mProgress=findViewById(R.id.progressBar1); } @Override public boolean onCreateOptionsMenu(Menumenu) { getMenuInflater().inflate(R.menu.activity_main,menu); return true ; } @Override public void onClick(Viewv) { switch (v.getId()) { case R.id.button1: btn1Click(); break ; default : break ; } } private void btn1Click() { mProgress.setVisibility(View.VISIBLE); new Thread() { @Override public void run() { final Stringstr=update(); Runnableaction= new Runnable() //该方法仍然是在main线程中完成的 { @Override public void run() //run里进行main线程的事件 { textView.setText(str); mProgress.setVisibility(View.GONE); Log.e( "runnable" ,Thread.currentThread().getName()); } }; /* *除Handler外的其他三种方法,适用于控件较少的场景 */ runOnUiThread(action); //方法一 textView.post(action); //方法二,post方法执行前会调用 mHandler.post(action); //方法三 mHandler.postDelayed(action, 3000 ); //方法三可以加个延时 } }.start(); } private Stringupdate() { return "更新完成!" ; } } 注: 1.handler.post这个函数的作用是把Runnable里面的run方法里面的这段代码发送到消息队列中,等待运行。如果handler是以UI线程消息队列为参数构造的,那么是把run里面的代码发送到UI线程中,等待UI线程运行这段代码。如果handler是以子线程线程消息队列为参数构造的,那么是把run里面的代码发送到子线程中,等待子线程运行这段代码。 本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1206265,如需转载请自行联系原作者

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

Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析(4)

2.MemoryBase 文章开始时说过,MemoryBase接口是建立在MemoryHeapBase接口的基础上的,它们都可以作为一个Binder对象来在进程间进行数据共享,它们的关系如下所示: MemoryBase类包含了一个成员变量mHeap,它的类型的IMemoryHeap,MemoryBase类所代表的匿名共享内存就是通过这个成员变量来实现的。 与MemoryHeapBase的分析过程一样,我们先来看MemoryBase类在Server端的实现,然后再来看它在Client端的实现。 MemoryBase在Server端实现的类图如下所示: MemoryBase类在Server端的实现与MemoryHeapBase类在Server端的实现是类似的,这里只要把IMemory类换成IMemoryHeap类、把BnMemory类换成BnMemoryHeap类以及MemoryBase类换成MemoryHeapBase类就变成是MemoryHeapBase类在Server端的实现了,因此,我们这里只简单分析IMemory类和MemoryBase类的实现。 IMemory类定义了MemoryBase类所需要实现的接口,这个类定义在frameworks/base/include/binder/IMemory.h文件中: classIMemory:publicIInterface { public: ...... virtualsp<IMemoryHeap>getMemory(ssize_t*offset=0,size_t*size=0)const=0; ...... void*pointer()const; size_tsize()const; ssize_toffset()const; }; 成员函数getMemory用来获取内部的MemoryHeapBase对象的IMemoryHeap接口;成员函数pointer()用来获取内部所维护的匿名共享内存的基地址;成员函数size()用来获取内部所维护的匿名共享内存的大小;成员函数offset()用来获取内部所维护的这部分匿名共享内存在整个匿名共享内存中的偏移量。 IMemory类本身实现了pointer、size和offset三个成员函数,因此,它的子类,即MemoryBase类,只需要实现getMemory成员函数就可以了。IMemory类的实现定义在frameworks/base/libs/binder/IMemory.cpp文件中: void*IMemory::pointer()const{ ssize_toffset; sp<IMemoryHeap>heap=getMemory(&offset); void*constbase=heap!=0?heap->base():MAP_FAILED; if(base==MAP_FAILED) return0; returnstatic_cast<char*>(base)+offset; } size_tIMemory::size()const{ size_tsize; getMemory(NULL,&size); returnsize; } ssize_tIMemory::offset()const{ ssize_toffset; getMemory(&offset); returnoffset; } MemoryBase类声明在frameworks/base/include/binder/MemoryBase.h文件中: classMemoryBase:publicBnMemory { public: MemoryBase(constsp<IMemoryHeap>&heap,ssize_toffset,size_tsize); ...... virtualsp<IMemoryHeap>getMemory(ssize_t*offset,size_t*size)const; ...... private: size_tmSize; ssize_tmOffset; sp<IMemoryHeap>mHeap; }; MemoryBase类实现在frameworks/base/libs/binder/MemoryBase.cpp文件中: MemoryBase::MemoryBase(constsp<IMemoryHeap>&heap, ssize_toffset,size_tsize) :mSize(size),mOffset(offset),mHeap(heap) { } sp<IMemoryHeap>MemoryBase::getMemory(ssize_t*offset,size_t*size)const { if(offset)*offset=mOffset; if(size)*size=mSize; returnmHeap; } 在它的构造函数中,接受三个参数,参数heap指向的是一个MemoryHeapBase对象,真正的匿名共享内存就是由它来维护的,参数offset表示这个MemoryBase对象所要维护的这部分匿名共享内存在整个匿名共享内存块中的起始位置,参数size表示这个MemoryBase对象所要维护的这部分匿名共享内存的大小。 成员函数getMemory的实现很简单,只是简单地返回内部的MemoryHeapBase对象的IMemoryHeap接口,如果传进来的参数offset和size不为NULL,还会把其内部维护的这部分匿名共享内存在整个匿名共享内存块中的偏移位置以及这部分匿名共享内存的大小返回给调用者。 这里我们可以看出,MemoryBase在Server端的实现只是简单地封装了MemoryHeapBase的实现。1 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966918,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

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

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册