参考:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-answers/html
http://www.cnblogs.com/dolphin0520/p/3958019.htmljava
1.Java 中多线程同步是什么?编程
在多线程程序下,同步能实现控制对共享资源的访问。若是没有同步,当一个 Java 线程在修改一个共享变量时,另一个线程正在使用或者更新同一个变量,这样容易致使程序出现错误的结果。安全
2.解释实现多线程的几种方法?数据结构
1> Java 线程能够实现 Runnable 接口:(当你打算多重继承时,优先选择实现 Runnable)多线程
2> 继承 Thread 类来实现:并发
三、Thread.start ()与 Thread.run ()有什么区别?this
Thread.start ()方法启动线程,使之进入就绪状态,当 cpu 分配时间该线程时,由 JVM 调度执行 run ()方法。start()并不表明线程当即能够执行了。spa
四、为何须要 run ()和 start ()方法,咱们能够只用 run ()方法来完成任务吗?.net
咱们须要 run ()和start ()这两个方法是由于 JVM 建立一个单独的线程不一样于普通方法的调用,因此这项工做由线程的 start 方法来完成,start 由本地方法实现,须要显示地被调用,使用这俩个方法的另一个好处是任何一个对象均可以做为线程运行,只要实现了 Runnable 接口,这就避免因继承了 Thread 类而形成的 Java 的多继承问题。
五、什么是 ThreadLocal 类,怎么使用它?
该类提供了线程局部变量。这些变量不一样于它们的普通对应物,由于访问一个变量(经过其 get 或 set 方法)的每一个线程都有本身的局部变量,它独立于变量的初始化副本。ThreadLocal 实例一般是类中的私有静态字段,它们但愿将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。
例如,在下面的类中,私有静态 ThreadLocal 实例(serialNum)为调用该类的静态 SerialNum.get() 方法的每一个线程维护了一个“序列号”,该方法将返回当前线程的序列号。(线程的序列号是在第一次调用 SerialNum.get() 时分配的,并在后续调用中不会更改。)
每一个线程都保持一个对其线程局部变量副本的隐式引用,只要线程是活动的而且 ThreadLocal 实例是可访问的;在线程消失以后,其线程局部实例的全部副本都会被垃圾回收(除非存在对这些副本的其余引用)。
六、何时抛出 IillegalMonitorStateException 异常,为何?
调用 wait ()/notify ()/notifyAll ()中的任何一个方法时,若是当前线程没有得到该对象的锁,那么就会抛出 IllegalMonitorStateException 的异常(也就是说程序在没有执行对象的任何同步块或者同步方法时,仍然尝试调用 wait ()/notify ()/notifyAll ()时)。因为该异常是 RuntimeExcpetion 的子类,因此该异常不必定要捕获(尽管你能够捕获只要你愿意).做为 RuntimeException,此类异常不会在 wait (),notify (),notifyAll ()的方法签名说起。
七、Sleep ()、suspend ()和 wait ()之间有什么区别?
Thread.sleep ()使当前线程在指定的时间处于“非运行”(Not Runnable)状态。线程一直持有对象的监视器。好比一个线程当前在一个同步块或同步方法中,其它线程不能进入该块或方法中。若是另外一线程调用了 interrupt ()方法,它将唤醒那个“睡眠的”线程。
注意:sleep ()是一个静态方法。这意味着只对当前线程有效,一个常见的错误是调用t.sleep (),(这里的t是一个不一样于当前线程的线程)。即使是执行t.sleep (),也是当前线程进入睡眠,而不是t线程。t.suspend ()是过期的方法,使用 suspend ()致使线程进入停滞状态,该线程会一直持有对象的监视器,suspend ()容易引发死锁问题。
object.wait ()使当前线程出于“不可运行”状态,和 sleep ()不一样的是 wait 是 object 的方法而不是 thread。调用 object.wait ()时,线程先要获取这个对象的对象锁,当前线程必须在锁对象保持同步,把当前线程添加到等待队列中,随后另外一线程能够同步同一个对象锁来调用 object.notify (),这样将唤醒原来等待中的线程,而后释放该锁。基本上 wait ()/notify ()与 sleep ()/interrupt ()相似,只是前者须要获取对象锁。
八、.在静态方法上使用同步时会发生什么事?
同步静态方法时会获取该类的“Class”对象,因此当一个线程进入同步的静态方法中时,线程监视器获取类自己的对象锁,其它线程不能进入这个类的任何静态同步方法。它不像实例方法,由于多个线程能够同时访问不一样实例同步实例方法。
九、当一个同步方法已经执行,线程可以调用对象上的非同步实例方法吗?
能够,一个非同步方法老是能够被调用而不会有任何问题。实际上,Java 没有为非同步方法作任何检查,锁对象仅仅在同步方法或者同步代码块中检查。若是一个方法没有声明为同步,即便你在使用共享数据 Java 照样会调用,而不会作检查是否安全,因此在这种状况下要特别当心。一个方法是否声明为同步取决于临界区访问(critial section access),若是方法不访问临界区(共享资源或者数据结构)就不必声明为同步的。
下面有一个示例说明:Common 类有两个方法 synchronizedMethod1()和 method1(),MyThread 类在独立的线程中调用这两个方法。
这里是程序的输出:
Running ThreadMyThread-1
synchronizedMethod1 called
Running ThreadMyThread-2
Method 1 called
synchronizedMethod1 done
Method 1 done
结果代表即便 synchronizedMethod1()方法执行了,method1()也会被调用。
十、在一个对象上两个线程能够调用两个不一样的同步实例方法吗?
不能,由于一个对象已经同步了实例方法,线程获取了对象的对象锁。因此只有执行完该方法释放对象锁后才能执行其它同步方法。看下面代码示例很是清晰:Common 类有 synchronizedMethod1()和 synchronizedMethod2()方法,MyThread 调用这两个方法。
十一、什么是死锁
死锁就是两个或两个以上的线程被无限的阻塞,线程之间相互等待所需资源。这种状况可能发生在当两个线程尝试获取其它资源的锁,而每一个线程又陷入无限等待其它资源锁的释放,除非一个用户进程被终止。就 JavaAPI 而言,线程死锁可能发生在一下状况。
当两个线程相互调用 Thread.join ()
当两个线程使用嵌套的同步块,一个线程占用了另一个线程必需的锁,互相等待时被阻塞就有可能出现死锁。
Java多线程中的死锁 死锁是指两个或两个以上的进程在执行过程当中,因争夺资源而形成的一种互相等待的现象,若无外力做用,它们都将没法推动下去。这是一个严重的问题,由于死锁会让你的程序挂起没法完成任务,死锁的发生必须知足如下四个条件:
十二、什么是线程饿死,什么是活锁?
线程饿死和活锁虽然不想是死锁同样的常见问题,可是对于并发编程的设计者来讲就像一次邂逅同样。
当全部线程阻塞,或者因为须要的资源无效而不能处理,不存在非阻塞线程使资源可用。JavaAPI 中线程活锁可能发生在如下情形:
当全部线程在程序中执行 Object.wait (0),参数为 0 的 wait 方法。程序将发生活锁直到在相应的对象上有线程调用 Object.notify ()或者 Object.notifyAll ()。 当全部线程卡在无限循环中。