java并发编程基础—生命周期与线程控制
一、线程生命周期
线程被创建启动以后,他既不是一启动就进入执行状态,也不是一直处于执行状态,在线程的生命周期中,它要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)五种状态
1、新建状态
当程序使用new关键字创建了一个线程后,该线程就处于新建状态
2、就绪状态
当线程对象调用了start()方法之后,该线程就处于就绪状态,java虚拟机会为其创建方法调用栈和程序计数器。
这个状态中的线程并没有开始执行线程,只是表示该线程可以运行了,至于何时运行,取决于JVM线程调度器调度。
3、运行状态
如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态。
4、阻塞状态
当运行状态的线程发生如下情况时,线程会进入阻塞状态:
(1)线程调用sleep()方法主动放弃所占用的处理器资源。
(2)线程调用了一个阻塞式IO方法,在该方法返回之前,该线程被阻塞
(3)线程试图获得一个同步监视器,但该同步监视器正被其他线程所持有。
(4)线程在等待某个通知(notify)
(5)程序调用了线程的suspend()方法将线程挂起,这个方法在jdk1.6中已经过时,它容易导致死锁,不建议使用。
针对上面阻塞状态,当发生下面特定情况可以解除阻塞状态:
(1)sleep()方法经过了指定时间。
(2)阻塞式IO方法已经返回
(3)线程成功获得了一个同步监视器。
(4)线程在等待某个通知时,其他线程发出了一个通知
(5)处于挂起的线程被调用了resume()恢复方法
5、线程死亡
线程结束后就处于死亡状态,有三种结束方式:
(1)run()或call()方法执行完成,线程正常结束
(2)线程抛出一个未捕获的Exception或者Error
(3)直接调用线程的stop()方法结束线程——容易死锁,不建议使用
isAlive()方法可以判断线程是否死亡,当处于就绪、运行、阻塞状态时返回true,处于新建、死亡状态时返回false。
已经死亡的线程不能重新启动,否则引发IllegalThreadStateException。
二、控制线程
java线程提供了一些简便的工具方法,利用这些方法可以很好的控制线程
1、join()
join()方法:让一个线程等待一个线程完成。
package threadtest; public class ThreadTest implements Runnable { @Overridepublic void run() {for(int i=0;i<30;i++) {System.out.println(Thread.currentThread().getName() + " " + i);}}public static void main(String[] args) throws InterruptedException {ThreadTest target1 = new ThreadTest();Thread t1 = new Thread(target1,"t1");t1.start();for(int i=0;i<30;i++) {System.out.println(Thread.currentThread().getName() + " " + i);//开始主线程和t1线程并发执行,当main线程的i到15时,调用了t1线程的join方法,//此时主线程等待t1线程,直到t1结束时才跑main,//join后,主线程处于阻塞状态if(i == 15) {t1.join();}}}}
2、线程睡眠 sleep()
如果需要让当前线程暂停一段时间,则可以使用sleep()方法
package threadtest;import java.time.LocalTime;public class ThreadTest implements Runnable {@Overridepublic void run() {for(int i=0;i<30;i++) {System.out.println(Thread.currentThread().getName() + " " + i +" "+ LocalTime.now());if(i == 15){try {Thread.sleep(10000);//10s} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) throws InterruptedException {ThreadTest target1 = new ThreadTest();Thread t1 = new Thread(target1,"t1");t1.start();} }
3、线程让步 yield()
yield()方法会让线程直接进入就绪状态,主要作用就是让当前线程暂停一下。完全有可能线程yield()后,线程调度器又将该线程调度出来执行。
yield()暂停后,只有优先级与当前线程相同或者优先级比当前线程更高的处于就绪状态的线程才有机会获得执行机会。
package threadtest;import java.time.LocalTime;public class ThreadTest implements Runnable {@Overridepublic void run() {for(int i=0;i<30;i++) {System.out.println(Thread.currentThread().getName() + " " + i +" "+ LocalTime.now());if(i == 15){Thread.yield();//线程让步 }}}public static void main(String[] args) throws InterruptedException {ThreadTest target1 = new ThreadTest();Thread t1 = new Thread(target1,"t1");t1.start();for(int i=0;i<10;i++) {System.out.println(Thread.currentThread().getName() + " " + i +" "+ LocalTime.now());}} }
sleep()和yield()方法的区别
(1)sleep暂停后会给其他线程机会,不会理会其他线程的优先级,但yield只给优先级相同或者更高的线程机会
(2)sleep将线程转为阻塞状态,yield将线程转为就绪状态
(3)sleep方法声明抛出了InterruptedException异常,所以用sleep要么捕捉该异常,要么抛出该异常。
(4)sleep比yield有更好的移植性,通常不建议使用yield方法来控制并发线程的执行
线程的优先级
每个线程执行时都有一定的优先级,优先级高的线程能获得更多的执行机会。每个线程的默认优先级与创建它的父线程优先级相同。默认情况下,main线程具有普通优先级
Thread类中 setPriority(int newPriority)和getPriority()方法分别设置和获取线程的优先级。
setPriority(int newPriority)的参数是一个整数,范围1-10;也可以是三个静态常量
MAX_PRIORITY:10
MIN_PRIORITY:1
NORM_PRIORITY:5
package threadtest;import java.time.LocalTime;public class ThreadTest implements Runnable {@Overridepublic void run() {for(int i=0;i<30;i++) {System.out.println(Thread.currentThread().getName() + " " + i +" "+ LocalTime.now());if(i == 15){Thread.yield();}}}public static void main(String[] args) throws InterruptedException {ThreadTest target1 = new ThreadTest();Thread t1 = new Thread(target1,"t1");Thread t2 = new Thread(target1,"t2");t2.setPriority(Thread.MAX_PRIORITY);//设置优先级 t1.start();t2.start();} }
转载于:https://www.cnblogs.com/jnba/p/10592945.html
java并发编程基础—生命周期与线程控制相关推荐
- Java并发编程的艺术-Java并发编程基础
第4章 Java并发编程基础 Java从诞生开始就明智地选择了内置对多线程的支持,这使得Java语言相比同一时期的其他语言具有明显的优势.线程作为操作系统调度的最小单元,多个线程能够同时执行,这将 ...
- Java并发编程基础--ThreadLocal
Java并发编程基础之ThreadLocal ThreadLocal是一个线程变量,但本质上是一个以ThreadLocal对象为键.任意对象为值的存储结构,这个结构依附在线程上,线程可以根据一个T ...
- 【Java并发编程】之二:线程中断
[Java并发编程]之二:线程中断 使用interrupt()中断线程 当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一 ...
- java 并发编程多线程_多线程(一)java并发编程基础知识
线程的应用 如何应用多线程 在 Java 中,有多种方式来实现多线程.继承 Thread 类.实现 Runnable 接口.使用 ExecutorService.Callable.Future 实现带 ...
- Java并发编程 基础知识学习总结
Java并发编程一直是Java程序员必须懂但又是很难懂的技术内容,这部分的内容我也是反复学习了好几遍才能理解.本篇博客梳理一下最近从<Java 并发编程的艺术>和他人的博客学习Java并发 ...
- 【Java并发编程的艺术】读书笔记——Java并发编程基础
学习参考资料:<Java并发编程的艺术> 文章目录 1.线程的几种状态 2.如何安全的终止线程 3.线程间通信(重要) 3.1共享内存 3.2消息传递 1.线程的几种状态 线程在运行的生命 ...
- java并发编程入门_探讨一下!Java并发编程基础篇一
Java并发编程想必大家都不陌生,它是实现高并发/高流量的基础,今天我们就来一起学习这方面的内容. 什么是线程?什么是进程?他们之间有什么联系? 简单来说,进程就是程序的一次执行过程,它是系统进行资源 ...
- 【Java 并发编程】【05】线程安全问题与线程同步
5. 线程安全问题与线程同步 多线程编程是有趣且复杂的事情,它常常容易突然出现"错误情况",这是由于系统的线程调度具有一定的随机性.即使程序在运行过程中偶尔会出现问题,那也是由于我 ...
- java并发编程基础系列(五): 创建线程的四种方式
线程的创建一共有四种方式: 继承于Thread类,重写run()方法: 实现Runable接口,实现里面的run()方法: 使用 FutureTask 实现有返回结果的线程 使用ExecutorSer ...
最新文章
- linux常用命令-date-clock-hwclock-type-whois--help-man-info-cal
- ant design pro 加载慢_ant design pro (九)引入外部模块
- 王志成/王之泰《面向对象程序设计(java)》第十一周学习总结
- Tools - 一些代码阅读的方法
- 上传图片即时显示图片
- 服务器显示AL018是什么意思,IIS服务器80端口却已被占用的问题
- 二分归并排序算法_第五篇排序算法|归并排序
- android系统(106)---Android Netd ndc
- Leetcode每日一题:203.remove-linked-list-elements(移除链表元素)
- cf723d Lakes in Berland
- Fragment Transactions和Activity状态丢失
- 2022-04-25 安装PostgreSQL的发现小bug
- 15条SQLite3语句
- 交换机配置web/telnet
- 微信红包封面催生暴利灰产:有人月入三十万
- 北理珠计算机学院学生会,梦回北理
- tf1.x版RandLA-Net源码解读(2):Dataset
- css3中的动画特效--跳动的篮球
- 人工智能笔记 2.1人工智能导论- 1.什么是AI,深度优先,广度优先,最优路径
- 【日常记录】Linux 系统 tar、rar、zip、7z、7za 压缩、解压命令
热门文章
- js高级程序设计笔记——DOM扩展
- 《移动数据挖掘》—— 第1章 引言 1.1 移动数据及其价值
- CDN的工作原理以及其中的一些技术-阿里
- http://m.blog.csdn.net/article/details?id=2630620
- 附加没有日志文件的数据库方法
- englis translate,word
- Google Maps API 进级:通过XML文档加载Gpolyline或者Gpolygon
- 书籍记录——C++大学基础教程(第五版)
- Python单元测试--使用装饰器实现测试跳过和预期故障
- MSI-X 之有别于MSI