Android 一些面试题

1 . synchronized  同步块
A.无论 synchronized 关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。
B.每个对象只有一个锁(lock)与之相关联。
C.实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
1 .  把 synchronized 当作函数修饰符时,示例代码如下:
Public synchronized  void  methodAAA()
{
//….
}
这也就是同步方法,那这时 synchronized 锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了 synchronized 关键字的方法。
 
 
2 . static  成员类:
静态成员类多了 static 关键字
如果声明成员类不要求访问外围实例,就要始终把 static 修饰符放在它的声明中。
因为如果使用非静态嵌套类的话,每个实例都将含有一个额外的指向外围对象的引用。保存这份引用要消耗时间和空间,并会导致外围实例在符合垃圾回收时却仍然得以保留。
非静态成员类的每个实例都隐含着与外围类的一个外围实例相关联。在非静态成员类的每个实例方法内部,可以调用外围实例上的方,或者利用修饰过的 this 构造获得外围实例的引用。而静态成员类可以独立于外围实例之外。
 
 
3 . Java 线程
状态:A、新状态。
实例化Thread对象,但没有调用start()方法时的状态。
ThreadTest tt = new  ThreadTest();   
或者Thread t = new  Thread (tt);
此时虽然创建了Thread对象,如前所述,但是它们不是活的,不能通过isAlive()测试。
 
B、就绪状态。
线程有资格运行,但调度程序还没有把它选为运行线程所处的状态。也就是具备了运行的条件,一旦被选中马上就能运行。
也是调用start()方法后但没运行的状态。此时虽然没在运行,但是被认为是活的,能通过isAlive()测试。而且在线程运行之后、或者被阻塞、等待或者睡眠状态回来之后,线程首先进入就绪状态。
 
C、运行状态。
从就绪状态池(注意不是队列,是池)中选择一个为当前执行进程时,该线程所处的状态。
 
D、等待、阻塞、睡眠状态。
阻塞BLOCKED:等待获取一个排它锁,等待进入一个同步区域。
无限期等待WAITING:等得其他线程显式地唤醒。
限期等待TIMED_WAITING:在一定时间之后会由系统自动唤醒。
 
这三种状态有一个共同点:线程依然是活的,但是缺少运行的条件,一旦具备了条就就可以转为就绪状态(不能直接转为运行状态)。另外,suspend()和stop()方法已经被废弃了,比较危险,不要再用了。
 
E、死亡状态。
一个线程的run()方法运行结束,那么该线程完成其历史使命,它的栈结构将解散,也就是死亡了。但是它仍然是一个Thread对象,我们仍可以引用它,就像其他对象一样!它也不会被垃圾回收器回收了,因为对该对象的引用仍然存在。
如此说来,即使run()方法运行结束线程也没有死啊!事实是,一旦线程死去,它就永远不能重新启动了,
也就是说,不能再用start()方法让它运行起来!如果强来的话会抛出IllegalThreadStateException异常。
 
静态Thread.yield()方法。
它的作用是让当前运行的线程回到可运行状态,以便让具有同等优先级的其他线程运行。用yield()方法的目的是让同等优先级的线程能适当地轮转。
 
非静态join()方法。
让一个线程加入到另一个线程的尾部。让B线程加入A线程,意味着在A线程运行完成之前,B线程不会进入可运行状态。
 
  object.notify()
唤醒在此对象锁上等待的单个线程。此方法只能由拥有该对象锁的线程来调用。
 
thread.join():在一个线程对象上调用,使当前线程等待这个线程对象对应的线程结束。
 
Thread.yield():暂停当前正在执行的线程对象,并执行其他线程。
 
thread.interrupt()
 
        中断线程,停止其正在进行的一切。中断一个不处于活动状态的线程不会有任何作用。
Thread.interrupted():检测当前线程是否已经中断,并且清除线程的中断状态(回到非中断状态)。
 
thread.isAlive():如果线程已经启动且尚未终止,则为活动状态。
 
thread.setDaemon():需要在start()方法调用之前调用。当正在运行的线程都是后台线程时,Java虚拟机将退出。否则当主线程退出时,其他线程仍然会继续执行。
 
 
线程停止的方法
1 .如果线程正在run的情况下可以使用 变量 例如
boolean  isRun;
while (isRun){***}
如果不在run的情况下:
我们可以使用interrupt()来打破阻塞的情况
 
 
这里还需要注意一点,当线程处于写文件的状态时,调用interrupt()不会中断线程。
阻塞的I/O
 
当线程被I/O阻塞的时候,调用interrupt()的情况是依赖与实际运行的平台的。在Solaris和Linux平台上将会抛出InterruptedIOException的异常,但是Windows上面不会有这种异常。所以,我们处理这种问题不能依靠于平台的实现
 
线程间通信
     管道流(pipe)用于在不同线程间直接传送数据。它有PipeInputStream和PipeOutputStream两个类支持。
 
Thread.sleep
线程休眠的目的是使线程让出CPU的最简单的做法之一,线程休眠时候,会将CPU资源交给其他线程,以便能轮换执行,当休眠一定时间后,线程会苏醒,进入准备状态等待执行。
 
4 .arraylist 和vector 的区别 :
ArrayList不具备线程同步的安全性,但速度较快,所以叫裸奔。
Vector具备线程安全。
Vector是同步的,ArrayList不是。
Vector 的 public 函数,都加了 synchronized 关键字,
 
HashMap 和 Hashtable的区别:
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。
Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。
 
5 . switch  case
switch 语句的判断条件可以接受 int , byte , char , short ,不能接受其他类型.
不过在Java SE 7 中, switch - case 语句可以支持字符串类型的数据变量
 
6 . Java的 值传递和引用传递
传值---传递基本数据类型参数
引用传递---对象作为参数
 
11  Android 主线程的讲解
 
  一个Android 程序默认情况下也只有一个进程Process,但可以有许多个线程Thread。
        在这么多Thread当中,有一个Thread,我们称之为UI Thread。UI Thread在Android程序运行的时候就被创建,是一个Process当中的主线程Main Thread,主要是负责控制UI界面的显示、更新和控件交互。在Android程序创建之初,一个Process呈现的是单线程模型,所有的任务都在一个线程中运行。因此,我们认为,UI Thread所执行的每一个函数,所花费的时间都应该是越短越好。
 
UI Thread如何和其他Thread一起工作的常用方法是:
         新建一个主线程的Handler实例,当做Listener去让子线程能将数据Push到主线程的Message Quene里,以便触发主线程的handlerMessage()函数,让主线程知道子线程的状态,并在主线程更新UI。
 
 
Handler 内部都有一个Looper一直在运转,Looper里不停的操作一个MessageQueue,Handler的sendMessage方法把消息插入到了这个mQueue,而Looper发现有了新的mQueue,就调用handleMessage接口来处理。
 
Handler类的构造函数就能看出来,虽然有四个构造函数,但每个构造函数里面都有Looper的身影,而且后面还跟着一个mQueue。
Looper是android为线程配备的一个工具,用来做线程间通讯,一个线程里只能有一个Looper。而且在activity启动时,android还为进程创建了一个MainLooper,插一句,应用程序的第一个线程,是主线程,其实就是进程,也称为根线程。
 
 
所以在主线程里面使用Handler的时候,你不需要新建Looper,而在子线程里使用Handler的时候,
你就必须构造一个Looper。
 
Looper用于封装了android线程中的消息循环,默认情况下一个线程是不存在消息循环(message loop)的,需要调用Looper.prepare()来给线程创建一个消息循环,调用Looper.loop()来使消息循环起作用,从消息队列里取消息,处理消息。
 
Handler 扮演了往MessageQueen上添加消息和处理消息的角色,就是通知执行一个任务sendMessage,post(Runable);,并loop到自己的任务的时候执行相关线程的业务逻辑。
Handler 创建的时候会关联一个loop,默认构造方法将关联当前的looper,不过可以set的。
 
一个线程可以有多个Handler,但只能有一个Looper.post发出的Runable对象最后被封装了message对象了。
 
handler的dispatchMessage是有looper调用的。
 
android的主线程也是一个looper线程(looper在android中运用很广),我们在其中创建的handler默认将关联主线程MQ。因此,利用handler的一个solution就是在activity中创建handler并将其引用传递给worker thread,worker thread执行完任务后使用handler发送消息通知activity更新UI
 
每个线程中的Looper对象其实是一个ThreadLocal,即线程本地存储(TLS)对象
ThreadLocal并不是一个Thread,而是Thread的局部变量
当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
 
8 .序列化的必要性
Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端。这就需要有一种可以在两端传输数据的协议。Java序列化机制就是为了解决这个问题而产生。
 
9 . service线程
1 )如果是service类中自己的方法,那就和UI线程在同一个线程中。
2 )如果你调用的是service中的binder对象的方法,就不是了,binder是在binder thread中处理。
一般是和启动service的那个activity是一个线程,但是不排除没有activity,直接开机就启动的service,如果service没有设定属性android:process= ":remote" 的话,service会和activity跑在同一个进程中,
 
3 )由于一个进程只有一个UI线程 service不是线程。可以在线程中工作。
可以在启动线程绑定其他线程,让其他线程在service里面运行。
 
activity,service之类的组件可以通过process属性设置,可以放到不同进程里
 
Service能管理子线程,而activity不好管理线程,因为系统会销毁。
service启动是在主线程上的,如果你想在service中处理很占时间的操作,你必须在service中开线程,这样可以降低activity没有响应的风险。service本身的一些方法还是在UI Thread中。service启动之后就不在主线程里面了。
 
Service跟Thread之间的通信:
 
Service创建Thread后,如果要对线程进行控制(启动,暂停,停止等),那么Service中应该保留线程的
引用,这不用多说。那么有了这个引用,Service就可以直接调用Thread的其它方法了。运行的线程要向Service发送消息的话,通常使用Handler就可以了:
android默认是不销毁县城的,activity 的销毁有时候并不会销毁主线程。
主线程和activity的销毁木有关系的。
 
10 . HandlerThread
 
Handler默认关联主线程,虽然要提供Runnable参数 ,但默认是直接调用Runnable中的run()方法。也就是默认下会在主线程执行,如果在这里面的操作会有阻塞,界面也会卡住。如果要在其他线程执行,可以使用HandlerThread。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值