Java 程序员面试中的多线程问题
很 多 核 心 Java 面 试 题 来 源 于 多 线 程 (Multi-Threading) 和 集 合 框 架 (Collections Framework),理解核心线程概念时,娴熟的实际经验是必需的。这篇文章收集了 Java 线程方面一些典型的问题,这些问题经常被高级工程师所问到。 0.Java 中多线程同步是什么? 在多线程程序下,同步能控制对共享资源的访问。如果没有同步,当一个 Java 线程在 修改一个共享变量时,另外一个线程正在使用或者更新同一个变量,这样容易导致程序 出现错误的结果。 1.解释实现多线程的几种方法? 一 Java 线程可以实现 Runnable 接口或者继承 Thread 类来实现,当你打算多重继 承时,优先选择实现 Runnable。 2.Thread.start ()与 Thread.run ()有什么区别? Thread.start ()方法(native)启动线程, 使之进入就绪状态, cpu 分配时间该线程时, 当 由 JVM 调度执行 run ()方法。
3.为什么需要 run ()和 start ()方法,我们可以只用 run ()方法来完成任务吗? 我们需要 run ()&;start ()这两个方法是因为 JVM 创建一个单独的线程不同于普通方法 的调用,所以这项
工作由线程的 start 方法来完成,start 由本地方法实现,需要显示 地被调用,使用这俩个方法的另外一个好处是任何一个对象都可以作为线程运行,只要 实现了 Runnable 接口, 这就避免因继承了 Thread 类而造成的
Java 的多继承问题。 4.什么是 ThreadLocal 类,怎么使用它?
ThreadLocal 是一个线程级别的局部变量,并非“本地线程”。ThreadLocal 为每个使用 该变量的线程提供了一个独立的变量副本, 每个线程修改副本时不影响其它线程对象的 副本(译者注)。 下面是线程局部变量(ThreadLocal variables)的关键点: 一个线程局部变量(ThreadLocal variables)为每个线程方便地提供了一个单独的变量。 ThreadLocal 实例通常作为静态的私有的(private static)字段出现在一个类中,这个类 用来关联一个线程。 当多个线程访问 ThreadLocal 实例时, 每个线程维护 ThreadLocal 提供的独立的变量 副本。
常用的使用可在 DAO 模式中见到,当 DAO 类作为一个单例类时,数据库链接 (connection)被每一个线程独立的维护,互不影响。(基于线程的单例) ThreadLocal 难于理解,下面这些引用连接有助于你更好的理解它。 《Good article on ThreadLocal on IBM DeveloperWorks 》、《理解 ThreadLocal》、 《Managing data : Good example》、《Refer Java API Docs》 5.什么时候抛出 InvalidMonitorStateException 异常,为什么? 调用 wait ()/notify ()/notifyAll ()中的任何一个方法时,如果当前线程没有获得该对象的 锁, 那么就会抛出 IllegalMonitorStateException 的异常(也就是说
程序在没有执行对象 的任何同步块或者同步方法时
,仍然尝试调用 wait ()/notify ()/notifyAll ()时)。由于该异 常是 RuntimeExcpetion 的子类,所以该异常不一定要捕获(尽管你可以捕获只要你愿 意).作为 RuntimeException,此类异常不会在 wait (),notify (),notifyAll ()的方法签名提 及。 6.Sleep ()、suspend ()和 wait ()之间有什么区别? Thread.sleep ()使当前线程在指定的时间处于“非运行”(Not Runnable)状态。线程一 直持有对象的监视器。比如一个线程当前在一个同步块或同步方法中,其它线程不能进 入该块或方法中。如果另一线程调用了 interrupt ()方法,它将唤醒那个“睡眠的”线程。 注意:sleep ()是一个静态方法。这意味着只对当前线程有效,一个常见的错误是调用 t.sleep (),(这里的 t 是一个不同于当前线程的线程)。即便是执行 t.sleep (),也是当
前线程进入睡眠,而不是 t 线程。t.suspend ()是过时的方法,使用 suspend ()导致线 程进入停滞状态,该线程会一直持有对象的监视器,suspend ()容易引起死锁问题。 object.wait