Java相关文章
线程的生命周期
- 新建 -> 就绪 -> 运行 -> 阻塞 -> 死亡
- 新建
- 实现Runnable接口和继承Thread可以得到一个线程类,new一个实例出来,线程就进入了初始状态
- 就绪
- 可运行状态只是说你资格运行,调度程序没有挑选到你,你就永远是可运行状态。
- 调用线程的start()方法,此线程进入可运行状态。
- 当前线程sleep()方法结束,其他线程join()结束,等待用户输入完毕,某个线程拿到对象锁,这些线程也将进入就绪状态。
- 当前线程时间片用完了,调用当前线程的yield()方法,当前线程从运行状态进入就绪状态。
- 锁池里的线程拿到对象锁后,进入可运行状态。
- 运行
- 线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。
- 阻塞
- 当前线程T调用Thread.sleep()方法,当前线程进入阻塞状态。
- 运行在当前线程里的其它线程t2调用join()方法,当前线程进入阻塞状态。
- 等待用户输入的时候,当前线程进入阻塞状态。
Thread常用方法
- Thread.currentThread() 返回当前执行的线程对象引用
- Thread.yield() 让步操作,让当前线程从正在运行状态变为就绪状态
- Thread.sleep() 让当先线程失眠
- Thread.start() 启动线程,线程进入就绪状态,虚拟机调度执行run方法
- Thread.run() run方法只是thread普通的方法,由jvm调用
- Thread.interrupt中断线程
- Thread.join 阻塞到线程执行完成
- setDaemon设置是否为守护线程
Thread.join()方法
- Thread中的join方法主要的作用是让join的线程加入当前线程,等加入的线程执行完之后才会执行当前线程。
- 本质上调用的Object.wait()实现现成的阻塞,所以Join方法被synchronize修饰。
- Join方法阻塞的是主线程,最终join的方法执行完通过notifyAll唤醒
Thread.start()与Thread.run()的区别
- start用来启动线程,线程进入就绪状态
- run方法只是thread普通的方法,在主线程里运行
- 线程的run方法是虚拟机直接调用的,如果没有运行线程(运行start方法) 而是在应用代码中直接调用了run方法,那么其实这个线程是运行在当前线程(调用run方法的那个线程中)违背了多线程初衷
wait()与sleep()的区别
- sleep方法是Thread类的方法,wait是object的方法
- sleep不释放锁,wait方法释放锁
- sleep必须捕获异常 ,wait不用捕获
怎么停止线程
- 在 run() 方法执行完毕后,该线程就终止了,设置好结束标志
- stop()方法
- 调用 stop() 方法会立刻停止 run() 方法中剩余的全部工作,包括在 catch 或 finally 语句中的,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭。
- 调用 stop() 方法会立即释放该线程所持有的所有的锁,导致数据得不到同步,出现数据不一致的问题。
- interrupt()终端异常
- 正确停止线程的方法
- 不会立刻停止异常,而是打上停止标记
如何控制多个线程按顺序执行
- 利用并发包里的Excutors的newSingleThreadExecutor产生一个单线程的线程池,而这个线程池的底层原理就是一个先进先出(FIFO)的队列。代码中executor.submit依次添加了123线程,按照FIFO的特性,执行顺序也就是123的执行结果,从而保证了执行顺序。
- join方法,join方法让当前执行线程阻塞直到调用join方法的线程结束运行