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 {
@Override
public 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 {
@Override
public 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 {
@Override
public 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 {
@Override
public 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();
}
}
java并发编程基础—生命周期与线程控制的更多相关文章
- Java并发1——线程创建、启动、生命周期与线程控制
内容提要: 线程与进程 为什么要使用多线程/进程?线程与进程的区别?线程对比进程的优势?Java中有多进程吗? 线程的创建与启动 线程的创建有哪几种方式?它们之间有什么区别? 线程的生命周期与线程控制 ...
- Java并发编程基础
Java并发编程基础 1. 并发 1.1. 什么是并发? 并发是一种能并行运行多个程序或并行运行一个程序中多个部分的能力.如果程序中一个耗时的任务能以异步或并行的方式运行,那么整个程序的吞吐量和可交互 ...
- 并发-Java并发编程基础
Java并发编程基础 并发 在计算机科学中,并发是指将一个程序,算法划分为若干个逻辑组成部分,这些部分可以以任何顺序进行执行,但与最终顺序执行的结果一致.并发可以在多核操作系统上显著的提高程序运行速度 ...
- Java并发编程(您不知道的线程池操作), 最受欢迎的 8 位 Java 大师,Java并发包中的同步队列SynchronousQueue实现原理
Java_并发编程培训 java并发程序设计教程 JUC Exchanger 一.概述 Exchanger 可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchan ...
- Java并发编程--基础进阶高级(完结)
Java并发编程--基础进阶高级完整笔记. 这都不知道是第几次刷狂神的JUC并发编程了,从第一次的迷茫到现在比较清晰,算是个大进步了,之前JUC笔记不见了,重新做一套笔记. 参考链接:https:// ...
- Java并发编程(您不知道的线程池操作)
Java并发编程(您不知道的线程池操作) 这几篇博客,一直在谈线程,设想一下这个场景,如果并发的线程很多,然而每个线程如果执行的时间很多的话,这样的话,就会大量的降低系统的效率.这时候就可以采用线程池 ...
- 【Java并发编程】之二:线程中断
[Java并发编程]之二:线程中断 使用interrupt()中断线程 当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一 ...
- java并发编程笔记(七)——线程池
java并发编程笔记(七)--线程池 new Thread弊端 每次new Thread新建对象,性能差 线程缺乏统一管理,可能无限制的新建线程,相互竞争,有可能占用过多系统资源导致死机或者OOM 缺 ...
- java并发编程笔记(五)——线程安全策略
java并发编程笔记(五)--线程安全策略 不可变得对象 不可变对象需要满足的条件 对象创建以后其状态就不能修改 对象所有的域都是final类型 对象是正确创建的(在对象创建期间,this引用没有逸出 ...
随机推荐
- 笔记-13-多线程 Thread方法 线程安全 生产者和消费者 死锁和阻塞 练习
题目1 编写程序,创建两个线程对象,一根线程循环输出"播放背景音乐",另一根线程循环输出"显示画面";要求: 1: 1个线程使用Runnable接口的匿名内部类 ...
- JAVA复习题(一)基础知识
类的构造方法描述正确的是( )A. 类中的构造方法不能省略B. 构造方法必须与类同名,但方法不能与class同名C. 构造方法在一个对象被new时执行D. 一个类只能有一个构造方法我的答案:C正确答案 ...
- 「题解」NWRRC2017 Joker
本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:洛谷 P7028.gym101612J. 题意概述 有一个长度为 \(n\) 的数列,第 \(i\) 个元素的值为 \(a ...
- 【NX二次开发】 获取体的面 UF_MODL_ask_body_faces
获取体的面 1 extern DllExport void ufsta(char *param, int *returnCode, int rlen) 2 { 3 UF_initialize(); 4 ...
- 聚类算法K-Means算法和Mean Shift算法介绍及实现
Question:什么是聚类算法 1.聚类算法是一种非监督学习算法 2.聚类是在没有给定划分类别的情况下,根据数据相似度进行样本分组的一种方法 3.理论上,相同的组的数据之间有相同的属性或者是特征,不 ...
- 合宙Luat直播间即将开启,你揭开行业奥秘,让你快人一步。
嗨~刚陪你们过儿童节 和你们一起成长的合宙Luat 又有新计划 -- 合宙Luat官方直播即将开启 - 敬请关注 - - 官方直播什么内容 - 可能是合宙研发动态 可能是新品发布资讯 可能是行业大咖分 ...
- Spring Cloud Data Flow整合Cloudfoundry UAA服务做权限控制
我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 前言 关于Spring Cloud Data Flow这里不多介绍,有兴趣可以看下面的文章.本文主要介绍如何整合Dat ...
- 『动善时』JMeter基础 — 50、使用JMeter测试WebService接口
目录 1.什么是WebService 2.WebService和SOAP的关系 3.什么是WSDL 4.测试WebService接口前的准备 (1)如何判断是WebService接口 (2)如何获取W ...
- MySQL 中存储时间的最佳实践
平时开发中经常需要记录时间,比如用于记录某条记录的创建时间以及修改时间.在数据库中存储时间的方式有很多种,比如 MySQL 本身就提供了日期类型,比如 DATETIME,TIMESTAMEP 等,我们 ...
- 10年程序员的编程语言感受与Go的结缘
因为小编最近在写两套教程,分别是Java语言基础教程和Go语言的基础教程,并且这 2 门语言,小编在实际的工作中也都有用过 而且 www.helloworld.net 社区的后台,就是用Go语言写的, ...