一、JDK、JRE和JVM三者之间关系:
1、所有的JAVA程序都会被编译成class文件,由虚拟机JVM和操作系统交互
2、JVM需要调用解释所需要的类库lib才可以执行class文件,JVM+lib=JRE即JAVA运行环境
3、JDK主要用于程序开发,最主要是编译器,包含了JRE,JAVA工具类和JAVA基础类库
二、怎么实现线程
实现Runnable接口或者继承Thread类来实现,当你打算多重继承时,优先选择实现Runnable
三、Thread.start()与Thread.run()有什么区别
调用start()后,线程会被放到等待队列,等待CPU调度。然后通过JVM,线程Thread会调用run()方法,执行本线程的线程体
四、为什么需要run()和start()方法,我们可以只用run()方法来完成任务吗
start()用来启动一个线程,当调用start()方法时,系统才会开启一个线程。run()只是一个线程里的一个函数,和多线程无关
1 public synchronized void start() { 2 if (threadStatus != 0) 3 throw new IllegalThreadStateException(); 4 group.add(this); 5 6 boolean started = false; 7 try { 8 start0(); 9 //private native void start0(),使用native修饰,Thread类要调用本地方法,要向JVM注册,这个方法调用了run方法 10 started = true; 11 } finally { 12 try { 13 if (!started) { 14 group.threadStartFailed(this); 15 } 16 } catch (Throwable ignore) { 17 } 18 } 19 }
五、什么是ThreadLocal类,怎么使用它
通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。而使用ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改
六、什么时候抛出InvalidMonitorStateException异常,为什么
调用wait()/notify()/notifyAll()中的任何一个方法时,如果当前线程没有获得该对象 的锁,那么就会抛出IllegalMonitorStateException的异常
七、多线程中sleep、supend和wait区别
共同点:都会阻塞当前线程
不同点:
1、sleep不会交出任何已获得的对象锁,是Thread类的方法,是线程用来控制自身流程的,调用此方法要捕捉InterruptedException异常
2、wait会交出调用wait对象的对象锁。是Object类中定义的方法,用来线程间的通信,而且wait存在notify方法来唤醒调用wait的线程。
3、suspend,使线程进入停滞状态,除非收到resume消息,否则该线程不会变回可执行状态
八、多线程中wait/notify区别
1、wait() 与 notify/notifyAll 方法必须在同步代码块中使用
wait() 与 notify/notifyAll() 是Object类的方法,在执行两个方法时,要先通过synchronized[‘s??kr?na?zd]获得锁
2、notify/notifyAll()执行后,并不立即释放锁,而是要等到执行完临界区中代码后,再释放
3、多线程中测试某个条件的变化用 if 还是用 while?
List中没有数据了,再还是有线程去执行删除数据的操作。因此,需要用while循环来判断条件的变化,而不是用if
九、在静态方法上使用同步时会发生什么事
Synchronized修饰静态方法,实际上是对该类对象加锁,俗称“类锁”
答案:http://blog.csdn.net/u010842515/article/details/65443084
十、Thread的join方法
1、Thread类中的join方法的主要作用就是同步,它可以使得线程之间的并行执行变为串行执行
2、join方法必须在线程start方法调用之后调用才有意义
3、join方法的原理就是调用相应线程的wait方法进行等待操作的,例如A线程中调用了B线程的join方法,则相当于在A线程中调用了B线程的wait方法,当B线程执行完(或者到达等待时间),B线程会自动调用自身的notifyAll方法唤醒A线程,从而达到同步的目的
十一、死锁
形成原因:循环等待,多线程申请多资源,形成了循环等待
1、互斥:进程在某一时间内独占资源;
2、持有:一个进程因请求资源而阻塞时,对已获得的资源保持不放;
3、不可剥夺:进程已获得资源,在末使用完之前,不能强行剥夺;
4、环形等待:若干进程之间形成一种头尾相接的循环等待资源关系;
解决方法:
1、针对2和3,引入事务机制,将所有上锁操作均作为事务对待,一旦开始上锁,即确保全部操作均可回退,同时通过锁管理器检测死锁,并剥夺资源
2、针对4,约定上锁的顺序必须一致
3、在尝试获取锁的时候加一个超时时间
4、死锁检测机制
每当一个线程获得了锁,会在线程和锁相关的数据结构中(map、graph等等)将其记下。除此之外,每当有线程请求锁,也需要记录在这个数据结构中。
当一个线程请求锁失败时,这个线程可以遍历锁的关系图看看是否有死锁发生。