线程的面试相关问题
一.什么是线程
线程是互相独立的,能够独立运行的子任务,并且每个线程都有自己运行的独立栈空间。所谓的多线程执行就是将CPU事件片,切换到不同的子任务。
在Java中,线程的执行,并不是基于CPU时间片的划分,而是基于抢占式的执行任务。Java中,一个线程对象在主线程中被创建,那么该线程对象拥有自己独立的栈空间,堆空间,和其他的对象一样,同样具有新生,运行,死亡,回收等机制,新创建的线程已经脱离了原有主线程的堆栈。
二.start()方法与run()方法的区别
在Thread类中,start()方法和run()方法都可以执行任务,但是,start()方法是通过创建一个线程去执行任务,而直接在当前线程中执行run()方法,则不会去创建一个新的线程去执行任务,也不会创建一个新的调用栈,这是start()方法与run()方法最重要的区别。
在线程执行完后,既run()方法执行完后,一个线程对象依然存活,但是该线程不允许再次允许start()方法,因为run()方法执行完毕后,表明该线程已死,如果强行执行start()方法,则JVM直接会抛出java.lang.IllegalThreadStateException异常,既线程是一次性用品。当然,只要该线程对象依然满足存活条件,也不会被GC,我们依然可以引用这个对象。
三.线程的优先级
因为Java的线程执行是基于抢占式的CPU,因此,对于不同优先级的线程执行,执行的顺序,有可能是按照优先级来执行,但是并不保证一定严格按照设置的优先级顺序执行,因此不能依靠线程的优先级来确保程序的执行顺序。
四.yield()方法
yield()方法是让当前持有CPU执行权的线程让出CPU给其他线程,但是要注意的是,yield()方法执行后线程会进入就绪状态,而进入就绪状态的线程,依然有可能会先得到CPU的执行权,既产生了连任。
五.wait()与notify()和notifyAll()方法
java中,可以使用wait与notify或notifyAll实现线程之间的通信。wait()是使当前的线程,进入等待或者休眠,而notify与notifyAll是用来唤醒通过调用wait()方法的线程而进入等待或休眠的线程,notify与notifyAll不同的是,notify只通知一个进入wait状态的线程,无法获知到底通知了那个线程,而notifyAll会通知所有进入wait状态的线程。
六.sleep()方法
sleep()方法是使当前的线程,进入休眠状态,可以设定具体的休眠时间,线程休眠结束后,开始进入就绪状态,等待获得CPU的执行权,与wait()方法不同的是,sleep()方法不会释放对象锁,而wait()方法会释放当前的对象锁。