线程周期的不同状态,有着如下几种
新建 NEW,线程被创建时候还没启动,是个内部状态
就绪 RUNNABLE,已经在JVM中执行,需要执行计算资源,等待系统分配CPU片段,就需要等待排队
阻塞Blocked 就是等待lock
等待 等待资源的操作,一个常见的场景类似消费者模式,等待任务时候的挂起
计时等待,进入条件和等待状态类似,调用的存在超时条件方法
终止 线程已经退出了,线程完成了使命,也可以称为死亡
第二次调用的时候,线程可能处于其他非NEW的状态,无法进行再次启动
在Java中,什么是一个简单的线程,线程必然是系统调度的最小单元,线程可以包含多个部分 栈 寄存器 本地存储,并且还会和其他线程个屏幕共享文件描述符 虚拟地址空间等
具体实现上,操作系统还将其分为了内核线程,用户线程,不过在现在的Java中,所有线程都是映射到系统内核线程的对象
伴随着Java发展,也有着Go语言中协程的推进,Java也跟进了Fiber的机制
在线程声明周期中可以进行改变状态的因素有哪些呢?
除了自身的start,线程还有多个join,父进程等待子进程结束后运行,yield告诉调度器,释放自己持有的CPU,还有些已经被标记为过时的resume stop suspend之类的api,JDK最新版本中 destory和stop方法已经被移除
Object提供的一些基础wait/notify/notifyAll的方法,如果持有某个对象的Mointor,其他线程必须等待Monitor的释放
Thread 和 Object中的并发并不好用
所以我们有了并发包的出现
然后是关于守护线程 Daemon Thread,应用需要一个长期的服务程序,
在所有线程都结束的时候也进行结束,这就是守护线程了
Thread daemonThread = new Thread();
daemonThread.setDaemon(true);
daemonThread.start();
还有就是慎用ThreadLocal,这是Java提供的一种保存线程私有信息的机制,方便在一个线程周期中使用上下文相关信息
但是内部是弱引用,但是回收要手动的依赖于部分api
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } } // … } |
所以key为null的时候,条目就很容易就被回收了
一般来说弱引用要配合引用队列使用,但是ThreadLocal并没有这么做
所以其回收要显式的触发,要等待线程的结束,所以回收对应的ThraedLoclMap,这也是OOM的来源,通常建议,应用最好自己去remove