1.线程的5种状态如何切换
线程的5种状态:新建、就绪、运行、阻塞、死亡。
切换:
sleep() : 让当前线程暂停一段时间;
yield() : 该方法与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。
join() : Thread的非静态方法join()让一个线程B“加入”到另外一个线程A的尾部。在A执行完毕之前,B不能工作。join() 方法主要是让调用该方法的thread完成run方法里面的东西后,再执行join()方法后面的代码
扩展:
Object类的wait(), notify(), notifyAll()方法:
wait()
释放占有的对象锁,线程进入等待池,释放cpu,而其他正在等待的线程即可抢占此锁,获得锁的线程即可运行程序。而sleep()不同的是,线程调用此方法后,会休眠一段时间,休眠期间,会暂时释放cpu,但并不释放对象锁。也就是说,在休眠期间,其他线程依然无法进入此代码内部。休眠结束,线程重新获得cpu,执行代码。wait()和sleep()最大的不同在于wait()会释放对象锁,而sleep()不会!
notify()
该方法会唤醒因为调用对象的wait()而等待的线程,其实就是对对象锁的唤醒,从而使得wait()的线程可以有机会获取对象锁。调用notify()后,并不会立即释放锁,而是继续执行当前代码,直到synchronized中的代码全部执行完毕,才会释放对象锁。JVM则会在等待的线程中调度一个线程去获得对象锁,执行代码。需要注意的是,wait()和notify()必须在synchronized代码块中调用。
notifyAll()
会唤醒所有等待(对象的)线程,尽管哪一个线程将会第一个处理取决于操作系统的实现。
2.线程是否可以重复启动,会有什么后果?
单一线程不能重复启动,否则报IllegalThreadStateException
扩展:
Thread.interrupt()方法不会中断一个正在运行的线程。这一方法实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。
3.synchronized 和 Lock 的区别
ReentrantLock 相对于固有锁synchronized,在某些vm版本上提供了比固有锁更高的性能,提供了更丰富的锁特性,比如可中断的锁,可等待的锁,平等锁以及非块结构的加锁。从代码上尽量用固有锁,jvm会对固有锁做一定的优化,并且代码可维护和稳定。只有在需要ReentrantLock的一些特性时,可以考虑用ReentrantLock实现。
另外,在并发量比较小的情况下,使用synchronized是个不错的选择,但是在并发量比较高的情况下,其性能下降很严重,此时ReentrantLock是个不错的方案。
4.悲观锁、乐观锁,如何自己实现一个乐观锁?
乐观锁是假设我已经拿到锁,悲观所是我必须拿到锁,前者用CAS,后者用Mutex。
利用CAS原理即可实现乐观锁,简单思路就是-比较和交换。
5.线程的实现方式
继承Thread类
实现Runnable接口
实现Callable<>接口(配合FutureTask类,用Thread类启动,Callable接口的call()方法带返回值)
另外:使用Executor framework (这会创建一个线程池)
采用继承Thread类方式:
1 优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。
2 缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。不能够很好的体现数据共享。
采用实现Runnable接口方式:
1 优点: 线程类只是实现了Runable接口,还可以继承其他的类。 可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况。能够很好的体现数据共享。
2 缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。
6.线程池拒绝策略
ThreadPoolExcutor.AbortPolicy() 线程池满时,抛出异常,默认操作
ThreadPoolExcutor.CallerRunsPolicy() 线程池满时,用调用者所在线程来运行任务
ThreadPoolExcutor.DiscardOldersPolicy() 线程池满时,不处理,直接丢掉丢弃队列里最旧的一个任务,并执行当前任务
ThreadPoolExcutor.DiscardPolicy() 线程池满时,不处理,直接丢掉
7.ThreadLocal 应用场景
在多线程环境下使用SimpleDateFormat,以及进行数据库连接关闭操作等。
扩展:ThreadLocal就是创建成员变量副本,Thread类中有一个ThreadLocal.ThreadLocalMap threadLocals成员变量,用以保存本地成员变量副本。
线程的5种状态:新建、就绪、运行、阻塞、死亡。
切换:
sleep() : 让当前线程暂停一段时间;
yield() : 该方法与sleep()类似,只是不能由用户指定暂停多长时间,并且yield()方法只能让同优先级的线程有执行的机会。
join() : Thread的非静态方法join()让一个线程B“加入”到另外一个线程A的尾部。在A执行完毕之前,B不能工作。join() 方法主要是让调用该方法的thread完成run方法里面的东西后,再执行join()方法后面的代码
扩展:
Object类的wait(), notify(), notifyAll()方法:
wait()
释放占有的对象锁,线程进入等待池,释放cpu,而其他正在等待的线程即可抢占此锁,获得锁的线程即可运行程序。而sleep()不同的是,线程调用此方法后,会休眠一段时间,休眠期间,会暂时释放cpu,但并不释放对象锁。也就是说,在休眠期间,其他线程依然无法进入此代码内部。休眠结束,线程重新获得cpu,执行代码。wait()和sleep()最大的不同在于wait()会释放对象锁,而sleep()不会!
notify()
该方法会唤醒因为调用对象的wait()而等待的线程,其实就是对对象锁的唤醒,从而使得wait()的线程可以有机会获取对象锁。调用notify()后,并不会立即释放锁,而是继续执行当前代码,直到synchronized中的代码全部执行完毕,才会释放对象锁。JVM则会在等待的线程中调度一个线程去获得对象锁,执行代码。需要注意的是,wait()和notify()必须在synchronized代码块中调用。
notifyAll()
会唤醒所有等待(对象的)线程,尽管哪一个线程将会第一个处理取决于操作系统的实现。
2.线程是否可以重复启动,会有什么后果?
单一线程不能重复启动,否则报IllegalThreadStateException
扩展:
Thread.interrupt()方法不会中断一个正在运行的线程。这一方法实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。
3.synchronized 和 Lock 的区别
ReentrantLock 相对于固有锁synchronized,在某些vm版本上提供了比固有锁更高的性能,提供了更丰富的锁特性,比如可中断的锁,可等待的锁,平等锁以及非块结构的加锁。从代码上尽量用固有锁,jvm会对固有锁做一定的优化,并且代码可维护和稳定。只有在需要ReentrantLock的一些特性时,可以考虑用ReentrantLock实现。
另外,在并发量比较小的情况下,使用synchronized是个不错的选择,但是在并发量比较高的情况下,其性能下降很严重,此时ReentrantLock是个不错的方案。
4.悲观锁、乐观锁,如何自己实现一个乐观锁?
乐观锁是假设我已经拿到锁,悲观所是我必须拿到锁,前者用CAS,后者用Mutex。
利用CAS原理即可实现乐观锁,简单思路就是-比较和交换。
5.线程的实现方式
继承Thread类
实现Runnable接口
实现Callable<>接口(配合FutureTask类,用Thread类启动,Callable接口的call()方法带返回值)
另外:使用Executor framework (这会创建一个线程池)
采用继承Thread类方式:
1 优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。
2 缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。不能够很好的体现数据共享。
采用实现Runnable接口方式:
1 优点: 线程类只是实现了Runable接口,还可以继承其他的类。 可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况。能够很好的体现数据共享。
2 缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。
6.线程池拒绝策略
ThreadPoolExcutor.AbortPolicy() 线程池满时,抛出异常,默认操作
ThreadPoolExcutor.CallerRunsPolicy() 线程池满时,用调用者所在线程来运行任务
ThreadPoolExcutor.DiscardOldersPolicy() 线程池满时,不处理,直接丢掉丢弃队列里最旧的一个任务,并执行当前任务
ThreadPoolExcutor.DiscardPolicy() 线程池满时,不处理,直接丢掉
7.ThreadLocal 应用场景
在多线程环境下使用SimpleDateFormat,以及进行数据库连接关闭操作等。
扩展:ThreadLocal就是创建成员变量副本,Thread类中有一个ThreadLocal.ThreadLocalMap threadLocals成员变量,用以保存本地成员变量副本。