资讯动态

多线程篇—(三)阻塞等待与休眠

发布时间:2026/9/9 9:11:08 来源:尧图企业网站定制
上篇讲述了线程的创建核心属性start 与 run 关系线程终止内容稍微回顾一下。线程创建方法一子类继承 Thread重写 run 方法。方法二子类实现 Runnable重写 run 方法。方法三一的基础上使用匿名内部类。方法四二的基础上使用匿名内部类。方法五基于 lambda 表达式。其中最推荐方法五因为非常简便。核心属性start 与 run虽然说都能成功运行程序但是这两不是一个级别的。run 只是线程跑起来的入口。start 是调用系统接口。线程终止每次执行循环绝大部分时间是在睡眠终止线程需要调用 interrupt 方法。原理看图示。整个线程被其中一个打包带走了.....为了能让代码继续运行下去其中一种方法是用 break 关键字。直接跳出整个循环往下执行。那要是不加 break 呢会继续 run 嘛试试就知道了。确实 run 下去了。java 中的线程终止不是一个“强制性”的措施不是 main 让 t 终止t 就一定会结束具体要看 t 线程本身代码咋写。阻塞等待多个线程之间CPU 随机调度并发执行虽然说效率高但是随机性也高。站在程序员的角度随机性越大意味着 BUG 概率越大。所以需要使用一个方法完成线程之间按顺序结束的效果。join 关键字能够要求多个线程之间结束的先后顺序。比如在主线程中调用 t.join就是等待到 t 线程先结束main 再执行。打开 jconsole 看线程状态。main 线程的处于死等如果 t 线程不结束join 会一直等下去除非外部干预不然不会结束。这种方法显然不是很好所以 join 提供了带参数的版本指定时间上限超出最大限度即使 t 还没结束join 也不会继续等下去。超时等待结果会输出几次 hello 是不确定的。CPU 分配的调度不同可能会出现两次或三次的概率也不同。休眠当前线程因为线程调度是不可控的所以这个方法只能保证实际休眠时间是大于等于设置参数的休眠时间的。我们最熟悉的 sleep 关键字没错依旧是它。写上 sleep (xxx) 后线程会暂时被带到内存休息一会等时间到了再唤醒到 CPU 上干活。着重说明一点sleep(0) 是 sleep 的特殊写法让线程立即放弃 CPU 资源给别人一些机会自己则等待重新被唤醒。当然ms 级别的时间。下面再回头细谈线程状态。线程状态在操作系统视角下分为 就绪 和 阻塞 状态。在 java 视角下分为以下几种newThread 对象已经实例好了但是还没 start。terminated内核中的线程结束了Thread 对象还有一口气。Runnable就绪。正在工作中 或 即将开始工作。Time_Waitting指定时间的阻塞线程不参与 CPU 调度休息会。Waitting死等线程任务结束 或者 被外部打断不然一直停着。Blocked锁着线程比较特殊的阻塞。画张图示理解为什么要画这个图多线程程序中理解线程状态是帮助调试程序的关键。如果发现代码中某个逻辑好像卡死了明明调用了好像没执行/走到一半卡住了。需要用到 jconsole / 其它工具查看当前进程的所有线程找到出问题的逻辑。如果是 time_waitting / waitting可能是代码的某个方法产生阻塞没有及时唤醒。如果是 Blocked怀疑是不是出现死锁。如果是 Runnable考虑逻辑的某些条件没有预期触发这些。然后看报错具体信息。两个线程数值总和一个线程算10k需要循环10k次两个线程需要1/2次以此类推。看似很简单的操作写出来会很简单吗public class Demo7 { public static int count0; public static void main(String[] args) { Thread tnew Thread(()-{ for (int i 0; i 5000; i) { count; } }); Thread t1new Thread(()-{ for (int i 0; i 5000; i) { count; } }); t.start(); t1.start(); System.out.println(countcount); } }不出意外count 等于0。至于原因和解决方法下一篇讲述。------------------------------------------------------------完---------------------------------------------------------------

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价