Android 面试题之J2EE

2017-12-05  本文已影响0人  侯蛋蛋_

所有知识点已整理成app

app下载地址

image.png

J2EE 部分:


1.Switch能否用string做参数?

在 Java 7 之前, switch 只能支持 byte 、 short 、 char 、 int 或者其对应的封装类以及 Enum 类型。在 Java 7 中, String 支持被加上了。

延伸(String是基本类型吗,可以被继承吗)
string是引用类型,底层是char数组实现的,string是final类,被在java中被final修饰的类是不可以被继承的,所以string不可以被继承

2. equals与==的区别:

==是判断两个变量或实例是不是指向同一个内存空间 equals是判断两个变量或实例所指向的内存空间的值是不是相同

3. Object有哪些公用方法?

5. 实际开发中软引用或者弱引用的使用场景:

1.WeakReference一般用来防止内存泄漏,要保证内存被虚拟机回收,SoftReference多用作来实现缓存机制(cache)。

2.SoftReference:软引用–>如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存,比如在图片加载框架中,通过软引用来实现内存缓存。

3.WeakReference:弱引用–>只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它 所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程, 因此不一定会很快发现那些只具有弱引用的对象。 Handler 弱引用,防止内存泄漏。

延伸

到底什么时候使用软引用,什么时候使用弱引用呢?

个人认为,如果只是想避免OutOfMemory异常的发生,则可以使用软引用。如果对于应用的性能更在意,想尽快回收一些占用内存比较大的对象,则可以使用弱引用。
还有就是可以根据对象是否经常使用来判断。如果该对象可能会经常使用的,就尽量用软引用。如果该对象不被使用的可能性更大些,就可以用弱引用。
另外,和弱引用功能类似的是WeakHashMap。WeakHashMap对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的回收,回收以后,其条目从映射中有效地移除。WeakHashMap使用ReferenceQueue实现的这种机制。

强弱软虚引用的相关文章

4.java有几种数据类型

提供了八种基本类型:

6. Hashcode的作用,与 equal 有什么区别

同样用于鉴定2个对象是否相等的,java集合中有 list 和 set 两类,其中 set不允许元素重复实现,那个这个不允许重复实现的方法,如果用 equal 去比较的话,如果存在1000个元素,你 new 一个新的元素出来,需要去调用1000次 equal 去逐个和他们比较是否是同一个对象,这样会大大降低效率。hashcode实际上是返回对象的存储地址,如果这个位置上没有元素,就把元素直接存储在上面,如果这个位置上已经存在元素,这个时候才去调用equal方法与新元素进行比较,相同的话就不存了,散列到其他地址上

HashCode的作用原理和实例解析

7. String、StringBuffer与StringBuilder的区别

1.String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象

2.StringBuffer和StringBuilder底层是 char[]数组实现的 StringBuffer是线程安全的,而StringBuilder是线程不安全的

8. Override和Overload的含义区别

Overload:1.方法的重载,只在方法之间发生2.方法名相同,并且区分大小写3.参数列表不同,具体是指参数的类型,个数,顺序不同4.返回值类型没有要求,可以相同,也可以不同

override:1.方法的覆盖,发生在父子类之间2.方法名称,参数表,返回值都相同,修饰符一样或者更宽3.静态方法只能被静态方法覆盖,没有多态4.子类不能抛出比父类更多的异常<指的是范围>

image.png

9. 抽象类和接口的区别

一个类只能继承单个类,但是可以实现多个接口 接口强调特定功能的实现,而抽象类强调所属关系 抽象类中的所有方法并不一定要是抽象的,你可以选择在抽象类中实现一些基本的方法。而接口要求所有的方法都必须是抽象的

10.解析XML的几种方式的原理与特点:DOM、SAX、PULL

11.wait()和sleep()的区别

12.面向对象都有哪些,以及你对他们的理解

答题技巧

这个问题没有标准答案,面试官主要考察的是面试者对于该问题的理解,因此,面试者在回答这个问题时应在回答理论后再结合自己熟悉的例子来说明。

面向对象

理解
面向过程
面向过程就是分析出解决问题的所需要的步骤,然后用函数把这些步骤一步一步实现,使用时依次调用即可。例如:一辆汽车用面向过程的思想去考虑它应该是这样的,如何启动汽车、如何起步、加速、刹车、熄火等操作,而汽车在这里并不是我们关心的 内容。

面向对象

面向对象是把构成问题的事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。例如:一辆汽车用面向对象的思想去实现时会以汽车为对象,汽车的发动机、传动箱、变速箱、刹车灯属性是汽车这个对象本身所具有的,做任何操作只要控制汽车即可。

13.JAVA多态的实现原理

抽象的来讲,多态的意思就是同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用) 实现的原理是动态绑定,程序调用的方法在运行期才动态绑定,追溯源码可以发现,JVM 通过参数的自动转型来找到合适的办法。

多态的实现原理

14.JAVA 垃圾回收与内存分配策略

14.1 垃圾回收是什么?

就是释放那些不再持有引用的对象的内存

14.2怎么判断一个对象是否需要收集?

14.3 Java的四种引用的区别

14.4 介绍垃圾回收机制

14.5 JAVA 中堆和栈的区别,说下Java的内存机制?

1.基本数据类型变量和对象的引用都是在栈分配的。

2.堆内存用来存放由new创建的对象和数组。

3.类变量(static修饰的变量),程序在一加载的时候就在堆中为类变量分配内存,堆中的内存地址存放在栈中实例变量:当你使用java关键字new的时候,系统在堆中开辟并不一定是连续的空间分配给变量,是根据零散的堆内存地址,通过哈希算法换算为一长串数字以表征这个变量在堆中的"物理位置”,实例变量的生命周期--当实例变量的引用丢失后,将被GC(垃圾回收器)列入可回收“名单”中,但并不是马上就释放堆中内存。

4.局部变量: 由声明在某方法,或某代码段里(比如for循环),执行到它的时候在栈中开辟内存,当局部变量一但脱离作用域,内存立即释放。

- 不同:
1.堆内存用来存放由new创建的对象和数组。 
2.栈内存用来存放方法或者局部变量等 
3.堆是先进先出,后进后出 
4.栈是后进先出,先进后出
- 相同
1.都是属于Java内存的一种 
2.系统都会自动去回收它,但是对于堆内存一般开发人员会自动回收它

15. Java 集合系列问题

15.1 ArrayList、LinkedList、Vector的区别

1、Vector、ArrayList都是以类似数组的形式存储在内存中,LinkedList则以链表的形式进行存储。
2、List中的元素有序、允许有重复的元素,Set中的元素无序、不允许有重复元素。
3、Vector线程同步,ArrayList、LinkedList线程不同步。
4、LinkedList适合指定位置插入、删除操作,不适合查找;ArrayList、Vector适合查找,不适合指定位置的插入、删除操作。
5、ArrayList在元素填满容器时会自动扩充容器大小的50%,而Vector则是100%,因此ArrayList更节省空间。

15.2 HashMap和 HashTable 的区别

HashTable比较老,是基于Dictionary 类实现的,HashMap 则是基于 Map接口实现的 HashTable 是线程安全的, HashMap 则是线程不安全的 HashMap可以让你将空值作为一个表的条目的key或value

17.什么是反射,在哪里需要用到?

做基础框架的时候会用得上,一般应用层面很少,不过这种东西,基本现在很多开源框架都已经给封装好了,自己基本用不着写。hibernate中用到,但不用自己写。Spring也用到了。经典的就是xml或者properties里面写上了配置,然后在Java类里面解析xml或properties里面的内容,得到一个字符串,然后用反射,根据这个字符串获得某个类的实例,这样就可以动态配置一些东西,不用每一次都要在代码里面去new或者做其他的事情,以后要改的话直接改配置文件,代码维护起来就很方便了,同时有时候要适应某些需求,Java类里面不一定能直接调用另外的方法,这时候也可以通过反射机制来实现。
总的来说,自己写的很少,具体什么时候要用那要看需求,无非就是根据一个String来得到你要的实体对象,然后调用它原来的东西。但是如果是要自己写框架的话,那就会用得比较多了。

18. 什么是线程池,线程池的作用是什么

答:线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。就好比原来去食堂打饭是每个人看谁抢的赢,谁先抢到谁先吃,有了线程池之后,就是排好队形,今天我跟你关系好,你先来吃饭。比如:一个应用要和网络打交道,有很多步骤需要访问网络,为了不阻塞主线程,每个步骤都创建个线程,在线程中和网络交互,用线程池就变的简单,线程池是对线程的一种封装,让线程用起来更加简便,只需要创一个线程池,把这些步骤像任务一样放进线程池,在程序销毁时只要调用线程池的销毁函数即可。

单个线程的弊端:a. 每次new Thread新建对象性能差b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或者OOM,c. 缺乏更多功能,如定时执行、定期执行、线程中断。

java提供的四种线程池的好处在于:a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。c. 提供定时执行、定期执行、单线程、并发数控制等功能。

2、Java 线程池

Java通过Executors提供四种线程池,分别为:

newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

5. JNI系列问题

5.1 如何使用JNI

  1. JAVA中声明native 方法如private native String printJNI(String inputStr);

  2. 使用javah工具生成.h头文件这时候头文件中就会自动生成对应的函数JNIEXPORT jstring JNICALL Java_com_wenming_HelloWorld_printJNI

  3. 实现JNI原生函数源文件,新建HelloWorld.c文件,对刚才自动生成的函数进行具体的逻辑书写,例如返回一个java叫做HelloWorld的字符串等

  4. 编译生成动态链接so文件**

  5. Java中调用Sysytem.load方法把刚才的so库加载进来,就可以调用native方法了

5.2 如何通过JNI传递String对象

Java的String和C++的string是不能对等起来的,所以当我们拿到.h文件下面的jstring对象,会做一次转换我们把jstring转换为C下面的char*类型, 获取值

6. OOM系列问题

6.1 什么OOM?

OOM全称是Out Of Merrory,Android系统的每一个应用程序都设置一个硬性的Dalvik Heap Size最大限制阈值,如果申请的内存资源超过这个限制,系统就会抛出OOM错误

6.2 内存泄漏有哪些场景以及解决方法

6.2 如何避免 OOM 问题的出现

1. 使用更加轻量的数据结构 例如,我们可以考虑使用ArrayMap/SparseArray而不是HashMap等传统数据结构。通常的HashMap的实现方式更加消耗内存,因为它需要一个额外的实例对象来记录Mapping操作。另外,SparseArray更加高效,在于他们避免了对key与value的自动装箱(autoboxing),并且避免了装箱后的解箱。

2. 避免在Android里面使用Enum Android官方培训课程提到过“Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.”,具体原理请参考《Android性能优化典范(三)》,所以请避免在Android里面使用到枚举。

3. 减小Bitmap对象的内存占用 Bitmap是一个极容易消耗内存的大胖子,减小创建出来的Bitmap的内存占用可谓是重中之重,,通常来说有以下2个措施: inSampleSize:缩放比例,在把图片载入内存之前,我们需要先计算出一个合适的缩放比例,避免不必要的大图载入。 decode format:解码格式,选择ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在很大差异

4.Bitmap对象的复用 缩小Bitmap的同时,也需要提高BitMap对象的复用率,避免频繁创建BitMap对象,复用的方法有以下2个措施 LRUCache : “最近最少使用算法”在Android中有极其普遍的应用。ListView与GridView等显示大量图片的控件里,就是使用LRU的机制来缓存处理好的Bitmap,把近期最少使用的数据从缓存中移除,保留使用最频繁的数据, inBitMap高级特性:利用inBitmap的高级特性提高Android系统在Bitmap分配与释放执行效率。使用inBitmap属性可以告知Bitmap解码器去尝试使用已经存在的内存区域,新解码的Bitmap会尝试去使用之前那张Bitmap在Heap中所占据的pixel data内存区域,而不是去问内存重新申请一块区域来存放Bitmap。利用这种特性,即使是上千张的图片,也只会仅仅只需要占用屏幕所能够显示的图片数量的内存大小

4. 使用更小的图片 在涉及给到资源图片时,我们需要特别留意这张图片是否存在可以压缩的空间,是否可以使用更小的图片。尽量使用更小的图片不仅可以减少内存的使用,还能避免出现大量的InflationException。假设有一张很大的图片被XML文件直接引用,很有可能在初始化视图时会因为内存不足而发生InflationException,这个问题的根本原因其实是发生了OOM。

5.StringBuilder 在有些时候,代码中会需要使用到大量的字符串拼接的操作,这种时候有必要考虑使用StringBuilder来替代频繁的“+”。

4.避免在onDraw方法里面执行对象的创建 类似onDraw等频繁调用的方法,一定需要注意避免在这里做创建对象的操作,因为他会迅速增加内存的使用,而且很容易引起频繁的gc,甚至是内存抖动。

6. 避免对象的内存泄露 android中内存泄漏的场景以及解决办法,参考上一问

7. ANR 系列问题

7.1 什么ANR

ANR全称Application Not Responding,意思就是程序未响应。如果一个应用无法响应用户的输入,系统就会弹出一个ANR对话框,用户可以自行选择继续等待亦或者是停止当前程序。一旦出现下面两种情况,则弹出ANR对话框

7.2 ANR是怎么引起的?

7.3 如何避免ANR问题的出现

基本思路就是把一些耗时操作放到子线程中处理

8. Asynctask问题

8.1 AsynTask为什么要设计为只能够一次任务?

最核心的还是线程安全问题,多个子线程同时运行,会产生状态不一致的问题。所以要务必保证只能够执行一次

8.2 AsynTask造成的内存泄露的问题怎么解决

比如非静态内部类AsynTask会隐式地持有外部类的引用,如果其生命周期大于外部activity的生命周期,就会出现内存泄漏

8.3 若Activity已经销毁,此时AsynTask执行完并且返回结果,会报异常吗?

当一个App旋转时,整个Activity会被销毁和重建。当Activity重启时,AsyncTask中对该Activity的引用是无效的,因此onPostExecute()就不会起作用,若AsynTask正在执行,折会报 view not attached to window manager 异常

同样也是生命周期的问题,在 Activity 的onDestory()方法中调用Asyntask.cancal方法,让二者的生命周期同步

8.4 Activity销毁但Task如果没有销毁掉,当Activity重启时这个AsyncTask该如何解决?

还是屏幕旋转这个例子,在重建Activity的时候,会回掉Activity.onRetainNonConfigurationInstance()重新传递一个新的对象给AsyncTask,完成引用的更新

9. Android触摸分发机制

9.1 介绍触摸事件的分发机制

enter image description here

(1) 事件从Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的View(ViewGroup)开始一直往下(子View)传递。子View可以通过onTouchEvent()对事件进行处理。

(2) 事件由父View(ViewGroup)传递给子View,ViewGroup可以通过onInterceptTouchEvent()对事件做拦截,停止其往下传递。

(3) 如果事件从上往下传递过程中一直没有被停止,且最底层子View没有消费事件,事件会反向往上传递,这时父View(ViewGroup)可以进行消费,如果还是没有被消费的话,最后会到Activity的onTouchEvent()函数。

(4) 如果View没有对ACTION_DOWN进行消费,之后的其他事件不会传递过来。

(5) OnTouchListener优先于onTouchEvent()对事件进行消费。

上面的消费即表示相应函数返回值为true。

9.2 View中 setOnTouchListener的onTouch,onTouchEvent,onClick的执行顺序

追溯到View的dispatchTouchEvent源码查看,有这么一段代码

public boolean dispatchTouchEvent(MotionEvent event) {  
        if (!onFilterTouchEventForSecurity(event)) {  
            return false;  
        }  

        if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
                mOnTouchListener.onTouch(this, event)) {  
            return true;  
        }  
        return onTouchEvent(event);  
    }

当以下三个条件任意一个不成立时,

函数会执行到onTouchEvent。在这里我们可以看到,首先执行的是mOnTouchListener.onTouch的方法,然后是onTouchEvent方法

继续追溯源码,到onTouchEvent()观察,发现在处理ACTION_UP事件里有这么一段代码

 if (!post(mPerformClick)) {  
                                    performClick();  
                                }

此时可知,onClick方法也在最后得到了执行

所以三者的顺序是:

  1. setOnTouchListener() 的onTouch
  2. onTouchEvent()
  3. onClick()

10. Dalvik虚拟机系列问题

10.1 什么是Dalvik虚拟机?

Dalvik虚拟机是Android平台的核心。它可以支持.dex格式的程序的运行,.dex格式是专为Dalvik设计的一种压缩格式,可以减少整体文件尺寸,提高I/O操作的速度,适合内存和处理器速度有限的系统。

10.2 Dalvik虚拟机的作用是什么?

Dalvik虚拟机主要是完成对象生命周期管理,内存回收,堆栈管理,线程管理,安全和异常管理等等重要功能。

10.3 Dalvik虚拟机与JVM有什么区别

10.4 每个应用程序对应多少个Dalvik虚拟机

11. 注册广播接收器有哪几种方式,有什么区别

12. 显示Intent与隐式Intent的区别

对明确指出了目标组件名称的Intent,我们称之为“显式Intent”。 对于没有明确指出目标组件名称的Intent,则称之为“隐式 Intent”。

对于隐式意图,在定义Activity时,指定一个intent-filter,当一个隐式意图对象被一个意图过滤器进行匹配时,将有三个方面会被参考到:

14. 不使用动画,怎么实现一个动态的 View?

1.SurfaceView
2.定时器或者线程

15. Postvalidata与Validata有什么区别?

invalidate()得在UI线程中被调动,在工作者线程中可以通过Handler来通知UI线程进行界面更新。

而postInvalidate()在工作者线程中被调用

16. 如何自定义ViewGroup?

1.Measure
Measure过程还是测量ViewGroup的大小,如果layout_widht和layout_height是match_parent或具体的xxxdp,就很简答了,直接调用setMeasuredDimension()方法,设置ViewGroup的宽高即可,如果是wrap_content,就比较麻烦了,我们需要遍历所有的子View,然后对每个子View进行测量,然后根据子View的排列规则,计算出最终ViewGroup的大小。

2.onLayout来按照我们想要的规则自定义子View排列。

3.ViewGroup在draw阶段,其实就是按照子类的排列顺序,调用子类的onDraw方法,因为我们只是View的容器, 本身一般不需要draw额外的修饰,所以往往在onDraw方法里面,只需要调用ViewGroup的onDraw默认实现方法即可。

17. View的绘制流程

enter image description here

measure()方法,layout(),draw()三个方法主要存放了一些标识符,来判断每个View是否需要再重新测量,布局或者绘制,主要的绘制过程还是在onMeasure,onLayout,onDraw这个三个方法中

1.onMesarue() 为整个View树计算实际的大小,即设置实际的高(对应属性:mMeasuredHeight)和宽(对应属性: mMeasureWidth),每个View的控件的实际宽高都是由父视图和本身视图决定的。

2.onLayout() 为将整个根据子视图的大小以及布局参数将View树放到合适的位置上。

3. onDraw() 开始绘制图像,绘制的流程如下

  1. 首先绘制该View的背景
  2. 调用onDraw()方法绘制视图本身 (每个View都需要重载该方法,ViewGroup不需要实现该方法)
  3. 如果该View是ViewGroup,调用dispatchDraw ()方法绘制子视图
  4. 绘制滚动条

18. 数据持久化的四种方式有哪些?

  1. 文件存储: 通过java.io.FileInputStream和java.io.FileOutputStream这两个类来实现对文件的读写,java.io.File类则用来构造一个具体指向某个文件或者文件夹的对象。

  2. SharedPreferences: SharedPreferences是一种轻量级的数据存储机制,他将一些简单的数据类型的数据,包括boolean类型,int类型,float类型,long类型以及String类型的数据,以键值对的形式存储在应用程序的私有Preferences目录(/data/data/<包名>/shared_prefs/)中,这种Preferences机制广泛应用于存储应用程序中的配置信息。

  3. SQLite数据库: 当应用程序需要处理的数据量比较大时,为了更加合理地存储、管理、查询数据,我们往往使用关系数据库来存储数据。Android系统的很多用户数据,如联系人信息,通话记录,短信息等,都是存储在SQLite数据库当中的,所以利用操作SQLite数据库的API可以同样方便的访问和修改这些数据。

  4. ContentProvider: 主要用于在不同的应用程序之间实现数据共享的功能,不同于sharepreference和文件存储中的两种全局可读写操作模式,内容提供其可以选择只对哪一部分数据进行共享,从而保证我们程序中的隐私数据不会有泄漏的风险

19. fragement里面可以再嵌套fragment?

20. Socker编程的步骤

image.png

21. Activity中如何动态的添加Fragment

image

22. Scrollview怎么判断是否滑倒底部

23. 什么是 MVC 模式?MVC 模式的好处是什么?

MVC的具体含义是:model+view+control,即模型+视图+控制它们各自处理自己的任务

(1)一个模型提供不同的多个视图表现形式,也能够为一个模型创建新的视图而无须重写模型。一旦模型的数据发生变化,模型将通知有关的视图,每个视图相应地刷新自己。

(2)模型可复用。因为模型是独立于视图的,所以可以把一个模型独立地移植到新的平台工作。

(3)提高开发效率。在开发界面显示部分时,你仅仅需要考虑的是如何布局一个好的用户界面;开发模型时,你仅仅要考虑的是业务逻辑和数据维护,这样能使开发者专注于某一方面的开发,提高开发效率。

24. 应用常驻后台,避免被第三方杀掉的方法,讲讲你用过的奇淫巧技?

  1. Service设置成START_STICKY kill 后会被重启(等待5秒左右),重传Intent,保持与重启前一样

  2. 通过 startForeground将进程设置为前台进程, 做前台服务,优先级和前台应用一个级别​,除非在系统内存非常缺,否则此进程不会被 kill

  3. 双进程Service: 让2个进程互相保护**,其中一个Service被清理后,另外没被清理的进程可以立即重启进程

  4. QQ黑科技: 在应用退到后台后,另起一个只有 1 像素的页面停留在桌面上,让自己保持前台状态,保护自己不被后台清理工具杀死

  5. 在已经root的设备下,修改相应的权限文件,将App伪装成系统级的应用 Android4.0系列的一个漏洞,已经确认可行

  6. 用C编写守护进程(即子进程) : Android系统中当前进程(Process)fork出来的子进程,被系统认为是两个不同的进程。当父进程被杀死的时候,子进程仍然可以存活,并不受影响。鉴于目前提到的在Android->- Service层做双守护都会失败,我们可以fork出c进程,多进程守护。死循环在那检查是否还存在,具体的思路如下(Android5.0以上的版本不可行)

  7. 用C编写守护进程(即子进程),守护进程做的事情就是循环检查目标进程是否存在,不存在则启动它。

  8. 在NDK环境中将1中编写的C代码编译打包成可执行文件(BUILD_EXECUTABLE)。主进程启动时将守护进程放入私有目录下,赋予可执行权限,启动它即可。

  9. 联系厂商,加入白名单

25.Context与ApplicationContext的区别,分别用在什么情况下

Application的Context是一个全局静态变量,SDK的说明是只有当你引用这个context的生命周期超过了当前activity的生命周期,而和整个应用的生命周期挂钩时,才去使用这个application的context。

在android中context可以作很多操作,但是最主要的功能是加载和访问资源。在android中有两种context,一种是 application context,一种是activity context,通常我们在各种类和方法间传递的是activity context。

26. 同一个应用程序的不同Activity可以运行在不同的进程中么?如果可以,举例说明;

27. Java中的线程同步有哪几种方式,举例说明;

28. dp, dip, dpi, px, sp是什么意思以及他们的换算公式?layout-sw400dp, layout-h400dp分别代表什么意思;

29. 如何让两个TextView在一个RelativeLayout水平居中显示;

30. 如何画出一个印章的图案

31. 如何实现一个字体的描边与阴影效果

32. 设计一个从网络请求数据,图片,并加载到列表的系统,画出客户端架构并简单的分析下;

33. 设计一个文件的断点续传系统;

34. 设计一个图片缓存加载机制

数据结构与算法部分:

  1. 给最外层的rootview,把这个根视图下的全部button背景设置成红色,手写代码,不许用递归
  2. 给一串字符串比如abbbcccd,输出a1b3c3d1,手写代码(注意有个别字符可能会出现十次以上的情况)
  3. 一个序列,它的形式是12349678,9是最高峰,经历了一个上升又下降的过程,找出里面的最大值的位置,要求效率尽可能高
  4. 二叉查找树的删除操作,手写代码
  5. 反转链表,手写代码
  6. 二分查找,手写代码
  7. 有海量条 url,其中不重复的有300万条,现在希望挑选出重复出现次数最高的 url,要求效率尽可能的高
  8. 一篇英语文章,去掉字符只留下k个,如何去掉才能使这k个字符字典序最小
  9. 弗洛伊德算法和 Dijkstra算法的区别?复杂度是多少?讲讲 Dijkstra算法的具体过程
  10. 反转字符串,要求手写代码,优化速度、优化空间
  11. 给出两个无向图,找出这2个无向图中相同的环路。手写代码
  12. 单例模式,手写代码
  13. 生产者与消费者,手写代码
  14. 二叉树镜像,手写代码
  15. 最长不重复子串(最长重复子串),手写代码

操作系统部分:

  1. 分别从操作系统的内存角度与进程线程角度解释分析堆,栈二者的区别
  2. 什么是事务?
  3. OSI七层模型有哪些,各层次的作用
  4. TCP的三次握手过程,四次挥手过程,为什么需要三次?
  5. 说说操作系统中进程的通信方式
  6. 浏览器输入地址之后,之后的过程
  7. 谈谈 HTTP 中Get 和 Post 方法的区别?
image.png

如何将一个java对象序列化到文件里

在java中能够被序列化的类必须先实现Serializable接口,该接口没有任何抽象方法只是起到一个标记作用。

// 创建一个User对象  
User user = new User();  
user.setId(1);  
user.setName("Mr XP.Wang");  
// 创建一个List对象  
List<String> list = new ArrayList<String>();  
list.add("My name");  
list.add(" is");  
list.add(" Mr XP.Wang");  
try {  
   ObjectOutputStream os = new ObjectOutputStream(  
      new FileOutputStream("C:/wxp.txt"));  
   os.writeObject(user);// 将User对象写进文件  
   os.writeObject(list);// 将List列表写进文件  
   os.close();  
...

读取

ObjectInputStream is = new ObjectInputStream(new FileInputStream(  
     "C:/wxp.txt"));  
User temp = (User) is.readObject();// 从流中读取User的数据  
System.out.println(temp.getId());  
System.out.println(temp.getName());  
List tempList = (List) is.readObject();// 从流中读取List的数据  
for (Iterator iterator = tempList.iterator(); iterator.hasNext();) {  
    System.out.print(iterator.next());  
}  
is.close();  

线程池的启动策略

线程池的启动策略

线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过,就算队列里面有任务,线程池也不会马上执行它们。

当调用execute() 方法添加一个任务时,线程池会做如下判断:

如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;

当一个线程完成任务时,它会从队列中取下一个任务来执行。

当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。

抽象与封装有何区别

答案说明

抽象是从众多的事物中抽取共同的、本质性的特征,而舍弃其非本质的特征。封装则是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。抽象是更通用的术语,它的实现可以由子类完成。例如,List类是一种JavaSE抽象,List的具体子类ArrayList和LinkedList。如果没有通过封装隐藏其内部状态,抽象也不可能实现,如果一个类暴露其内部状态,它不能在其内部完全掌控改变这个状态,那么这也不是抽象。封装是作为抽象的一部分。封装是对象封装它自己的状态,并对外部隐藏,该类以外的其他类必须通过它的方法进行交互,但不能直接访问该类的状态。所以封装的类是为抽象了有关其状态的实现细节。

谈一谈JVM的内存结构和内存分配

Java内存模型

java内存分配

Java的类加载器的种类都有哪些

加载器种类

根类加载器(Bootstrap) --C++写的 ,看不到源码。扩展类加载器(Extension) --加载位置 :jrelibext中。系统(应用)类加载器(SystemApp) --加载位置 :classpath中。自定义加载器(必须继承ClassLoader)。

什么是值传递和引用传递

对象被值传递,意味着传递了对象的一个副本。因此,就算是改变了对象副本,也不会影响原对象的值

同步方法和同步代码块的区别是什么

在java语言中,每一个对象有一把锁。线程可以使用synchronized关键字来获取对象上的锁。synchronized关键字可应用在方法级别(粗粒度锁)或者是代码块级别(细粒度锁)。

多线程有什么弊端

1.降低了一个进程里面的线程的执行频率。

2.对线程进行管理要求额外的 CPU开销。

3.线程的使用会给系统带来上下文切换的额外负担。

4.公有变量的同时读或写。当多个线程需要对公有变量进行写操作时,后一个线程往往会修改掉前一个线程存放的数据,发生线程安全问题。

5.线程的死锁。即较长时间的等待或资源竞争以及死锁等多线程症状。

实现接口方式和继承方式有什么区别

1.Java中是不允许类实现多继承的,但是如果一个A类中有一部分代码需要多线程执行,采用第一种方法实现的话,就继承了Thread类,不能再继续继承其他类,限制了A类功能的扩展。

2.Java已经考虑到这种情况,采用第二种实现多线程的方法的话,既可以在继承其他功能类的同时,可以通过实现接口的方法实现多线程。

3.实现接口的好处:避免了单继承的局限性。

抽象类可以没有抽象方法吗?

抽象类可以没有抽象方法,但是这样的抽象类无实际使用意义,除非是想要一个类不能被直接实例化,则可以定义为无抽象方法的抽象类

iterator和Listiterator的区别是什么

1.Iterator可用来遍历Set和ListJavaSE,但是ListIterator只能用来遍历List。

2.Iterator对JavaSE只能是前向遍历,ListIterator既可以前向也可以后向。

3.ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。

Java中Exception和Error有什么区别

Exception和Error都是Throwable的子类。Exception用于用户程序可以捕获的异常情况。Error是错误,不能被用户程序捕获。

Java中什么是构造函数?什么是构造函数重载?什么是复制构造函数?

java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?

字节流,字符流。字节流继承于InputStream OutputStream,字符流继承于InputStreamReaderOutputStreamWriter。在java.io包中还有许多其他的流,主要是为了提高性能和使用方便。

Serializable和Parcelable的区别?

说说你对线程池的理解

答案解析:

使用线程池的原因:

线程池的分类:

线程数解析:

创建规则:

一个任务通过execute(Runnable)方法欲添加到线程池时:

终止和关闭线程池:

hreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown()和shutdownNow(),其中:

Java中实现多态的机制是什么?

靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。

描述一下JVM加载class文件的原理机制?

JVM加载class文件的原理机制

finalize()方法什么时候被调用?析构函数(finalization)的目的是什么?

在释放对象占用的内存之前,垃圾收集器会调用对象的finalize()方法。一般建议在该方法中释放对象持有的资源。

在释放对象占用的内存之前,垃圾收集器会调用对象的finalize()方法。一般建议在该方法中释放对象持有的资源。

不会,在下一个垃圾回收周期中,这个对象将是可被回收的。

GC是什么? 为什么要有GC?

答案解析:

GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。

简述synchronized 和java.util.concurrent.locks.Lock的异同?

主要相同点:

Lock能完成synchronized所实现的所有功能

主要不同点:

Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放

Java中的泛型是什么?使用泛型的好处是什么?

这是在各种Java泛型面试中,一开场你就会被问到的问题中的一个,主要集中在初级和中级面试中。那些拥有Java1.4或更早版本的开发背景的人都知道,在JavaSE中存储对象并在使用前进行类型转换是多么的不方便。泛型防止了那种情况的发生。它提供了编译期的类型安全,确保你只能把正确类型的对象放入JavaSE中,避免了在运行时出现ClassCastException。

JavaSE类框架的基本接口有哪些?

JavaJavaSE类提供了一套设计良好的支持对一组对象进行操作的接口和类。

问答题 为什么JavaSE类没有实现Cloneable和Serializable接口?

克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。因此,应该由JavaSE类的具体实现来决定如何被克隆或者是序列化。

Java中的HashMap的工作原理是什么?

Java中的HashMap是以键值对(key-value)的形式存储元素的。HashMap需要一个hash函数,它使用hashCode() 和equals()方法从JavaSE添加和检索元素。当调用put()方法的时候,HashMap会计算key的hash值,然后把键值对存储在JavaSE 中合适的索引上。如果key已经存在了,value会被更新成新值。HashMap的一些重要的特性是它的容量(capacity),负载因子(load factor)和扩容极限(threshold resizing)。

hashCode()和equals()方法的重要性体现在什么地方?

Java中的HashMap使用hashCode()和equals()方法来确定键值对的索引,当根据键获取值的时候也会用到这两个方法。如果没 有正确的实现这两个方法,两个不同的键可能会有相同的hash值,因此,可能会被JavaSE认为是相等的。而且,这两个方法也用来发现重复元素。所以这两个方法 的实现对HashMap的精确性和正确性是至关重要的。

数组(Array)和列表(ArrayList)有什么区别?什么时候应该使用Array而不是ArrayList?

下面列出了Array和ArrayList的不同点:

Comparable和Comparator接口是干什么的?列出它们的区别。

Comparable和Comparator接口

Java提供了只包含一个compareTo()方法的Comparable接口。这个方法可以个给两个对象排序。具体来说,它返回负数,0,正数来表明输入对象小于,等于,大于已经存在的对象。
Java提供了包含compare()和equals()两个方法的Comparator接口。compare()方法用来给两个输入参数排序,返 回负数,0,正数表明第一个参数是小于,等于,大于第二个参数。equals()方法需要一个对象作为参数,它用来决定输入参数是否和 comparator相等。只有当输入参数也是一个comparator并且输入参数和当前comparator的排序结果是相同的时候,这个方法才返回 true。

HashSet和TreeSet有什么区别?

HashSet和TreeSet的区别

List<? extends T>和List <? super T>之间有什么区别 ?

这两个List的声明都是限定通配符的例子,List<? extends T>可以接受任何继承自T的类型的List,而List<? super T>可以接受任何T的父类构成的List。例如List<? extends Number>可以接受List或List。

Array中可以用泛型吗?

Array事实上并不支持泛型,这也是为什么Joshua Bloch在Effective Java一书中建议使用List来代替Array,因为List可以提供编译期的类型安全保证,而Array却不能。

Java中List<Object>和原始类型List之间的区别?

原始类型和带参数类型之间的主要区别是,在编译时编译器不会对原始类型进行类型安全检查,却会对带参数的类型进行检查,通过使用Object作为类型,可以告知编译器该方法可以接受任何类型的对象,比如String或Integer。这道题的考察点在于对泛型中原始类型的正确理解。它们之间的第二点区别是,你可以把任何带参数的类型传递给原始类型List,但却不能把List传递给接受List的方法,因为会产生编译错误。

解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法?

栈(stack)、堆(heap)和方法区(method area)

你了解大O符号(big-O notation)么?

大O符号

什么是线程局部变量?

线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。Java提供 ThreadLocal 类来支持线程局部变量,是一种实现线程安全的方式。但是在管理环境下(如 web 服务器)使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命周期比任何应用变量的生命周期都要长。任何线程局部变量一旦在工作完成后没有释放,Java 应用就存在内存泄露的风险。

Java中能创建volatile数组吗?

能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不是整个数组。如果改变引用指向的数组,将会受到 volatile 的保护,但是如果多个线程同时改变数组的元素,volatile 标示符就不能起到之前的保护作用了。

volatile能使得一个非原子操作变成原子操作吗?

一个典型的例子是在类中有一个 long 类型的成员变量。如果你知道该成员变量会被多个线程访问,如计数器、价格等,你最好是将其设置为 volatile。为什么?因为Java中读取long类型变量不是原子的,需要分成两步,如果一个线程正在修改该 long 变量的值,另一个线程可能只能看到该值的一半(前 32 位)。但是对一个volatile型的long或double变量的读写是原子。

你对volatile修饰符的使用有过什么实践?

一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写。double 和 long 都是64位宽,因此对这两种类型的读是分为两部分的,第一次读取第一个 32 位,然后再读剩下的 32 位,这个过程不是原子的,但 Java 中 volatile 型的 long 或 double 变量的读写是原子的。volatile 修复符的另一个作用是提供内存屏障(memory barrier),例如在分布式框架中的应用。简单的说,就是当你写一个 volatile 变量之前,Java 内存模型会插入一个写屏障(write barrier),读一个 volatile 变量之前,会插入一个读屏障(read barrier)。意思就是说,在你写一个 volatile 域时,能保证任何线程都能看到你写的值,同时,在写之前,也能保证任何数值的更新对所有线程是可见的,因为内存屏障会将其他所有写的值更新到缓存。

volatile 类型变量提供什么保证?

volatile变量提供顺序和可见性保证,例如,JVM或者JIT为了获得更好的性能会对语句重排序,但是volatile类型变量即使在没有同步块的情况下赋值也不会与其他语句重排序。volatile提供happens-before的保证,确保一个线程的修改能对其他线程是可见的。某些情况下,volatile 还能提供原子性,如读64位数据类型,像 long 和 double 都不是原子的,但 volatile 类型的 double 和 long 就是原子的。

Java 中 ++ 操作符是线程安全的吗?

不是线程安全的操作。它涉及到多个指令,如读取变量值,增加,然后存储回内存,这个过程可能会出现多个线程交差。

Java中的两种异常类型是什么?他们有什么区别?

Java中有两种异常:受检查的(checked)异常和不受检查的(unchecked)异常。不受检查的异常不需要在方法或者是构造函数上声 明,就算方法或者是构造函数的执行可能会抛出这样的异常,并且不受检查的异常可以传播到方法或者是构造函数的外面。相反,受检查的异常必须要用 throws语句在方法或者是构造函数上声明。

列出一些你常见的运行时异常?

常见的运行时异常

Java中什么是构造函数?什么是构造函数重载?什么是复制构造函数?

构造函数

short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗

过程如下:

数组有没有length()方法?String有没有length()方法?

数组没有length()方法,有length 的属性。String 有length()方法。JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆。

在Java中,如何跳出当前的多重嵌套循环?

你打车上了高速,发现在司机在兜圈子。于是你要他找个路口出去,这个路口肯定有牌子,不然你和司机都不知道从哪出。

语言也是一样的, 在最外层循环前加一个标记如A,然后用break A;可以跳出多重循环。

Java中支持带标签的break和continue语句,作用有点类似于C和C++中的goto语句,但是就像要避免使用goto一样,应该避免使用带标签的break和continue,因为它不会让你的程序变得更优雅,很多时候甚至有相反的作用,所以这种语法其实不知道更好。

当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

是值传递。Java语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的。

Java中的final关键字有哪些用法?

final的作用:

&和&&的区别?

&运算符有两种用法:

1)按位与。

2)逻辑与。

注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。

抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?

都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

阐述静态变量和实例变量的区别。

静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。

final、finally、finalize有什么区别?

区别如下:

当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B?

不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。因为非静态方法上的synchronized修饰符要求执行方法时要获得对象的锁,如果已经进入A方法说明对象锁已经被取走,那么试图进入B方法的线程就只能在等锁池(注意不是等待池哦)中等待对象的锁。

char型变量中能不能存储一个中文汉字,为什么?

char类型可以存储一个中文汉字,因为Java中使用的编码是Unicode(不选择任何特定的编码,直接使用字符在字符集中的编号,这是统一的唯一方法),一个char类型占2个字节(16比特),所以放一个中文是没问题的。

什么是不可变对象(immutable object)?

不可变对象指对象一旦被创建,状态就不能再改变。任何修改都会创建一个新的对象,如 String、Integer及其它包装类。

什么是隐式类型转换?什么是显式类型转换?

当将占位数少的类型赋值给占位数多的类型时,Java自动使用隐式类型转换(如int型转为long型)。当把在级别高的变量的值赋给级别底变量时,必须使用显示类型转换运算(如double型转为float型)。

解释什么是类方法,什么是实例方法

static修饰的方法是类方法,无static修饰的方法是实例方法。

堆内存和客栈内存的区别是什么

线程的对内存控件是共享的,栈内存控件才是独立的(堆共享,栈独立)

构造方法能否被重写?为什么?

不能,因为构造方法不能被继承,所以不能重写。

不能,因为构造方法不能被继承,所以不能重写。

java关键字一律小写。所以无所谓区分大小写,大写的不是关键字。

java关键字一律小写。所以无所谓区分大小写,大写的不是关键字。

Java使用unicode字符集,所以常量共有65535个。

简述一个java程序执行的过程?

首先编写java源文件(扩展名为.java的文本文档)。用javac命令把源文件编译成字节码文件.class文件,再用java命令执行字节码文件。

静态内部类、内部类、匿名内部类,为什么内部类会持有外部类的引用?持有的引用是this?还是其它?

静态内部类:使用static修饰的内部类内部类:就是在某个类的内部又定义了一个类,内部类所嵌入的类称为外部类匿名内部类:使用new生成的内部类因为内部类的产生依赖于外部类,持有的引用是类名.this。

我们能创建一个包含可变对象的不可变对象吗?

我们是可以创建一个包含可变对象的不可变对象,你只需要谨慎一点,不要共享可变对象的引用就可以了,如果需要变化时,就返回原对象的一个拷贝。

Java中try catch finally的执行顺序

先执行try中代码,运行至某一行发生异常时try中的代码将不会被执行,转而执行catch中的代码,最后一定会执行finally中代码。

Java中应该使用什么数据类型来代表价格?

如果不是特别关心内存和性能的话,使用BigDecimal,否则使用预定义精度的double类型。

我们能将 int 强制转换为 byte 类型的变量吗?如果该值大于 byte 类型的范围,将会出现什么现象?

面试官问你这个问题,你就说:我们可以做强制转换,但是Java中int是32位的,而byte是8位的,所以,如果强制转化是,int类型的高24位将会被丢弃,byte类型的范围是从 -128 到 128。

switch是否能作用在byte上,是否能作用在long上,是否能作用在String上?

switch支持使用byte类型,不支持long类型,String支持在java1.7引入

我能在不进行强制转换的情况下将一个 double 值赋值给 long 类型的变量吗?

面试官问你这个问题,你就说:没有强制类型转换的前提下将一个 double 不能赋值给 long 类型的变量,因为 double 类型的范围要比 long 类型更大,因此要做强制转换。

int和Integer 哪个会占用更多的内存?

经验总结:

尾巴带个er的,那肯定内存用得多,因为你还得new它。

Integer对象会占用更多的内存。Integer是一个对象,需要存储对象的元数据。但是 int 是一个原始类型的数据,所以占用的空间更少。

为什么Java中的String是不可变的(Immutable)?

经验总结:

其实就是设计Java内库的那个大神,认为字符串经常被用到,如果在内存里new那么多同样的东西,很占位置。那干脆就弄成不可变的,这样大家共享同样的字符串,就不会出问题。

Java中的构造器链是什么?

经验总结:

说实话,我也是第一次听到这个说法。直到有一个哥们去面试回来告诉我面试官问了他这么一个问题。我才明白,现在的面试官都喜欢玩这些。

后来想了想,不就是我构造函数里调用了另外一个构造函数么?

当你从一个构造器中调用另一个构造器,就是Java 中的构造器链。这种情况只在重载了类的构造器的时候才会出现。

简述正则表达式及其用途。

经验总结:

这种问题一般不会用嘴巴问你,最多就是简答或者填空题里给你来一发,也太简单了。

在编写处理字符串的程序时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。。

Java中是如何支持正则表达式操作的?

面试经验:

说实话,正则很有用,但平时也确实用得不多。正则里各种火星文符号也没那么容易记住,我们只要记得一些简单API就行了。 一下几个String里常用的方法,能说几个出来就OK。

Java中的String类提供了支持正则表达式操作的方法,包括:matches()、replaceAll()、replaceFirst()、split()。此外,Java中可以用Pattern类表示正则表达式对象,它提供了丰富的JavaSE进行各种正则表达式操作。

什么情况会产生死锁?

产生死锁的四个必要条件?

互斥条件:一个资源每次只能被一个进程使用。
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

上一篇 下一篇

猜你喜欢

热点阅读