1.List有哪几种?(ArrayList和LinnkedList的区别?Vector是什么?区别?)【如何往ArrayList和LinkedList插数据?中间插和头插?】
ArrayList:底层由数组结构实现,数组在内存中的存储顺序是连续的,对集合中的元素可以进行快速访问,更适合用来随机查询数据。
LinkedList:底层由双向链表结构实现,通过节点来存储下一个元素的位置,对集合中的元素可以方便的增加与删除,更适合用于大量修改。
Vector:Vector与ArrayList的区别就是Vector是线程安全的集合,在需要线程安全而且对效率要求比较低的情况下,使用Vector。
插入位置的选取对LinkedList有很大的影响,
因为LinkedList在插入时需要向移动指针到指定节点, 才能开始插入,,一旦要插入的位置比较远,LinkedList就需要一步一步的移动指针, 直到移动到插入位置,这就解释了, 为什么节点值越大, 时间越长, 因为指针移动需要时间。
而ArrayList是数据结构, 可以根据下标直接获得位置, 这就省去了查找特定节点的时间,所以对ArrayList的影响不是特别大。
总结: 虽然会出现上面的情况, 可是因为ArrayList可以使用下标直接获取数据,所以在使用查询的时候一般选择ArrayList,而进行删除和增加时,LinkedList比较方便,所以一般还是使用LinkedList比较多。
Arraylist和linkedlist的区别
ArrayList和LinkedList都是实现了List接口的容器类,用于存储一系列的对象引用。他们都可以对元素的增删改查进行操作。
对于ArrayList,它在集合的末尾删除或添加元素所用的时间是一致的,但是在列表中间的部分添加或删除时所用时间就会大大增加。但是它在根据索引查找元素的时候速度很快。
对于LinkedList则相反,它在插入、删除集合中任何位置的元素所花费的时间都是一样的,但是它根据索引查询一个元素的时候却比较慢。
ArrayList和LinkedList的大致区别:
1.ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表结构。
2.对于随机访问的get和set方法,ArrayList要优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。
2.死锁的条件?
产生死锁的原因主要是:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之
一不满足,就不会发生死锁。
死锁的解除与预防:
理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和
解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确
定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态
的情况下占用资源。因此,对资源的分配要给予合理的规划。
3.如何停止线程?
线程属于一次性消耗品,在执行完run()方法之后线程便会正常结束了,线程结束后便会销毁,不能再次start,只能重新建立新的线程对象,但有时run()方法是永远不会结束的。例如在程序中使用线程进行Socket监听请求,或是其他的需要循环处理的任务。在这种情况下,一般是将这些任务放在一个循环中,如while循环。当需要结束线程时,如何退出线程呢?
有三种方法可以结束线程:
1.设置退出标志,使线程正常退出,也就是当run()方法完成后线程终止
2.使用interrupt()方法中断线程
3.使用stop方法强行终止线程(不推荐使用,Thread.stop, Thread.suspend, Thread.resume 和Runtime.runFinalizersOnExit 这些终止线程运行的方法已经被废弃,使用它们是极端不安全的!)
前两种方法都可以实现线程的正常退出;第3种方法相当于电脑断电关机一样,是不安全的方法。
1.使用退出标志终止线程
一般run()方法执行完,线程就会正常结束,然而,常常有些线程是伺服线程。它们需要长时间的运行,只有在外部某些条件满足的情况下,才能关闭这些线程。使用一个变量来控制循环,例如:最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或false来控制while循环是否退出,代码示例:
public class ThreadSafe extends Thread {
public volatile boolean exit = false;
public void run() {
while (!exit){
//do something
}
}
}
定义了一个退出标志exit,当exit为true时,while循环退出,exit的默认值为false.在定义exit时,使用了一个Java关键字volatile,这个关键字的目的是使exit同步,也就是说在同一时刻只能由一个线程来修改exit的值.
2.使用interrupt()方法中断当前线程
使用interrupt()方法来中断线程有两种情况:
1.线程处于阻塞状态,如使用了sleep,同步锁的wait,socket中的receiver,accept等方法时,会使线程处于阻塞状态。当调用线程的interrupt()方法时,会抛出InterruptException异常。阻塞中的那个方法抛出这个异常,通过代码捕获该异常,然后break跳出循环状态,从而让我们有机会结束这个线程的执行。通常很多人认为只要调用interrupt方法线程就会结束,实际上是错的, 一定要先捕获InterruptedException异常之后通过break来跳出循环,才能正常结束run方法。
代码示例:
public class ThreadSafe extends Thread {
public void run() {
while (true){
try{
Thread.sleep(5*1000);//阻塞5妙
}catch(InterruptedException e){
e.printStackTrace();
break;//捕获到异常之后,执行break跳出循环。
}
}
}
}
2.线程未处于阻塞状态,使用isInterrupted()判断线程的中断标志来退出循环。当使用interrupt()方法时,中断标志就会置true,和使用自定义的标志来控制循环是一样的道理。
代码示例:
public class ThreadSafe extends Thread {
public void run() {
while (!isInterrupted()){
//do something, but no throw InterruptedException
}
}
}
为什么要区分进入阻塞状态和和非阻塞状态两种情况了,是因为当阻塞状态时,如果有interrupt()发生,系统除了会抛出InterruptedException异常外,还会调用interrupted()函数,调用时能获取到中断状态是true的状态,调用完之后会复位中断状态为false,所以异常抛出之后通过isInterrupted()是获取不到中断状态是true的状态,从而不能退出循环,因此在线程未进入阻塞的代码段时是可以通过isInterrupted()来判断中断是否发生来控制循环,在进入阻塞状态后要通过捕获异常来退出循环。因此使用interrupt()来退出线程的最好的方式应该是两种情况都要考虑:
代码示例:
public class ThreadSafe extends Thread {
public void run() {
while (!isInterrupted()){ //非阻塞过程中通过判断中断标志来退出
try{
Thread.sleep(5*1000);//阻塞过程捕获中断异常来退出
}catch(InterruptedException e){
e.printStackTrace();
break;//捕获到异常之后,执行break跳出循环。
}
}
}
}
3.使用stop方法终止线程
程序中可以直接使用thread.stop()来强行终止线程,但是stop方法是很危险的,就象突然关闭计算机电源,而不是按正常程序关机一样,可能会产生不可预料的结果,不安全主要是:thread.stop()调用之后,创建子线程的线程就会抛出ThreadDeatherror的错误,并且会释放子线程所持有的所有锁。一般任何进行加锁的代码块,都是为了保护数据的一致性,如果在调用thread.stop()后导致了该线程所持有的所有锁的突然释放(不可控制),那么被保护数据就有可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。因此,并不推荐使用stop方法来终止线程。
4:一个线程有几个Handler?
无数个
因为在每个activity里面都能new Handler
找到一篇很强的分析博客https://blog.csdn.net/carson_ho/article/details/51290360
5:一个线程里面有几个Looper?如何保证?
一个线程里面只有一个Looper,Looper相当于handler工作流程中的一个动力去让MessageQueue滚动起来,Looper函数的执行是通过Thread启动的,相当于打开Looper的开关
首先先整理Handler的工作流程