《浅谈——Java多线程面试问题以及基础知识》由会员分享,可在线阅读,更多相关《浅谈——Java多线程面试问题以及基础知识(52页珍藏版)》请在金锄头文库上搜索。
1、 北大青鸟华美官网: 多线程和并发问题是 Java 技术面试中面试官比较喜欢问的问题之一。在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握 Java 多线程基础知识来对应日后碰到的问题。Java 多线程面试问题1.进程和线程之间有什么不同?一个进程是一个独立(selfcontained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java 运行环境是一个包含了不同的类和程序的单一进程。线程可以被称为轻量级进程。线程需要较少的资源来创建和驻留在进程中,并且可以共享进程中的资源。2.多线程编程的好处是什么? 北大青鸟华美官网: 在多线程程序中,
2、多个线程被并发的执行以提高程序的效率,CPU不会因为某个线程需要等待资源而进入空闲状态。多个线程共享堆内存(heapmemory),因此创建多个线程去执行一些任务会比创建多个进程更好。举个例子,Servlets 比 CGI 更好,是因为 Servlets 支持多线程而CGI 不支持。3.用户线程和守护线程有什么区别?当我们在 Java 程序中创建一个线程,它就被称为用户线程。一个守护线程是在后台执行并且不会阻止 JVM 终止的线程。当没有用户线程在运行的时候,JVM 关闭程序并且退出。一个守护线程创建的子线程依然是守护线程。守护线程在没有用户线程可服务时自动离开,在 Java 中比较特殊的线程
3、是被称为守护(Daemon)线程的低级别线程。这个线程具有最低的优先级,用于为系统中的其它对象和线程提供服务。将一个用户线程设置为守护线程的方式是在线程对象创建之前调用线程对象的setDaemon 方法。典型的守护线程例子是 JVM 中的系统资源自动回收线程,我们所熟悉的 Java 垃圾回收线程就是一个典型的守护线程,当我们的程序中不再有任何运行中的 Thread,程序就不会再产生垃圾,垃圾回收器也就无事可做,所以当垃圾回收线程是 Java 虚拟机上仅剩的线程时,Java 虚拟机会自动离开。它始终在低级别的状态中运行,用于实时 北大青鸟华美官网: 监控和管理系统中的可回收资源。守护进程(Dae
4、mon )是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。也就是说守护线程不依赖于终端,但是依赖于系统,与系统“同生共死”。那 Java 的守护线程是什么样子的呢。当 JVM中所有的线程都是守护线程的时候,JVM 就可以退出了;如果还有一个或以上的非守护线程则 JVM 不会退出。守护线程并非虚拟机内部可以提供,用户也可以自行的设定守护线程,方法:publicfinalvoidsetDaemon(booleanon) ;但是有几点需要注意:1)、thread.setDaemon(true) 必须在 thread.start 之前设置,否则会跑出一个
5、IllegalThreadStateException 异常。你不能把正在运行的常规线程设置为守护线程。2)、在 Daemon 线程中产生的新线程也是 Daemon 的。3)、不是所有的应用都可以分配给 Daemon 线程来进行服务,比如读写操作或者计算逻辑。因为在 DaemonThread 还没来的及进行操作时,虚拟机可能已经退出了。java view plain copy 北大青鸟华美官网: 1. 4.我们如何创建一个线程?有两种创建线程的方法:一是实现 Runnable 接口,然后将它传递给 Thread 的构造函数,创建一个 Thread 对象;二是直接继承 Thread类。若想了解更
6、多可以阅读这篇关于如何在 Java 中创建线程的文章。实现 Runnable 接口:java view plain copy1. public class Test 2. public static void main(String args) 3. System.out.println(主线程 ID:+Thread.currentThread.getId); 北大青鸟华美官网: 4. MyRunnable runnable = new MyRunnable;5. Thread thread = new Thread(runnable);6. thread.start;7. 8. java v
7、iew plain copy1. class MyRunnable implements Runnable2. public MyRunnable 3. 4. Override5. public void run 6. System.out.println(子线程 ID:+Thread.currentThread.getId);7. 8. Runnable 的中文意思是“任务”,顾名思义,通过实现 Runnable接口,我们定义了一个子任务,然后将子任务交由 Thread 去执行。注意,这种方式必须将 Runnable 作为 Thread 类的参数,然后通过 Thread 的start 方法来
8、创建一个新线程来执行该子任务。如果调用 Runnable 的 北大青鸟华美官网: run 方法的话,是不会创建新线程的,这根普通的方法调用没有任何区别。事实上,查看 Thread 类的实现源代码会发现 Thread 类是实现了Runnable 接口的。继承 Thread 类:java view plain copy1. public class Test 2. public static void main(String args) 3. MyThread thread = new MyThread;4. thread.start;5. 6. 7.8.9. class MyThread ext
9、ends Thread10. private static int num = 0;11.12. public MyThread13. num+; 北大青鸟华美官网: 14. 15.16. Override17. public void run 18. System.out.println(主动创建的第+num+个线程);19. 20. 5.有哪些不同的线程生命周期?线程是一个动态执行的过程,它也有一个从产生到死亡的过程。(1)生命周期的五种状态新建(newThread)当创建 Thread 类的一个实例(对象)时,此线程进入新建状态(未被启动)。例如:Threadt1=newThread;就
10、绪(runnable)线程已经被启动,正在等待被分配给 CPU 时间片,也就是说此时线程正在就绪队列中排队等候得到 CPU 资源。例如:t1.start;运行(running )线程获得 CPU 资源正在执行任务(run 方法),此时除非此线程自动放弃 CPU 资源或者有优先级更高的线程进入,线程将一直运行到结束。 北大青鸟华美官网: 死亡(dead )当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。自然终止:正常运行 run 方法后终止异常终止:调用 stop 方法让一个线程终止运行堵塞(blocked)由于某种原因导致正在运行的线程让出 CPU 并
11、暂停自己的执行,即进入堵塞状态。正在睡眠:用 sleep(longt)方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。正在等待:调用 wait 方法。(调用 motify 方法回到就绪状态)被另一个线程所阻塞:调用 suspend 方法。(调用 resume 方法恢复)6.可以直接调用 Thread 类的 run 方法么?当然可以,但是如果我们调用了 Thread 的 run 方法,它的行为就会和普通的方法一样,为了在新的线程中执行我们的代码,必须使用Thread.start 方法。7.如何让正在运行的线程暂停一段时间? 北大青鸟华美官网: 我们可以使用 Thread
12、 类的 Sleep 方法让线程暂停一段时间。需要注意的是,这并不会让线程终止,一旦从休眠中唤醒线程,线程的状态将会被改变为 Runnable,并且根据线程调度,它将得到执行。8.你对线程优先级的理解是什么?每一个线程都是有优先级的,一般来说,高优先级的线程在运行时会具有优先权,但这依赖于线程调度的实现,这个实现是和操作系统相关的(OSdependent)。我们可以定义线程的优先级,但是这并不能保证高优先级的线程会在低优先级的线程前执行。线程优先级是一个 int 变量(从 1-10),1 代表最低优先级,10 代表最高优先级。线程的优先级以及设置线程的优先级是为了在多线程环境中便于系统对线程的调
13、度,优先级高的线程将优先执行。一个线程的优先级设置遵从以下原则:线程创建时,子继承父的优先级。线程创建后,可通过调用 setPriority 方法改变优先级。线程的优先级是 1-10 之间的正整数。 北大青鸟华美官网: 1-MIN_PRIORITY10-MAX_PRIORITY5-NORM_PRIORITY如果什么都没有设置,默认值是 5。但是不能依靠线程的优先级来决定线程的执行顺序。线程的优先级调度策略线程调度器选择优先级最高的线程运行。但是,如果发生以下情况,就会终止线程的运行:线程体中调用了 yield 方法,让出了对 CPU 的占用权。线程体中调用了 sleep 方法,使线程进入睡眠
14、状态。线程由于 I/O 操作而受阻塞。另一个更高优先级的线程出现。在支持时间片的系统中,该线程的时间片用完。java view plain copy 北大青鸟华美官网: 1. package .secn.thead;2. /第一种方案3. class MyThead implements Runnable4. 5. public void run6. 7. for (int i = 1; i AAA);10. 11. 12. 13. /第二种方案14. class MyThread2 extends Thread15. public void run16. for (int i = 1; i
15、list = new ArrayList;4. Vector vector = new Vector;5. long start = System.currentTimeMillis;6. for(int i=0;i vector = new Vector;3. public static void main(String args) throws InterruptedException 4. while(true) 5. for(int i=0;i10) 22. 北大青鸟华美官网: 23. 24. 25. 26. 在我机器上运行的结果:正如大家所看到的,这段代码报错了:数组下标越界。也许有朋友会问:Vector 是线程安全的,为什么还会报这个错?很简单,对于 Vector,虽然能保证每一个时刻只能有一个线程访问它,但是不排除这种可能:当某个线程在某个时刻执行这句时:java view plain copy1. for(int i=0;i vector = new Vector;3. public static void main(String arg