java基础知识回顾之java Thread类学习(四)--线程的状态以及转化使用的方法介绍
java基础知识回顾之java Thread类学习(十)--线程的状态以及转化使用的方法介绍
线程的概述:
线程是程序的多个执行路径,执行调度的单位,依托于进程存在。线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间叫做线程栈,是建立线程的时候由系统分配的,主要用来保存线程内部的数据,如线程执行函数中定义的变量。
java中多线程是一种抢占机制而不是分时机制。抢占机制是指CPU资源师被多个线程所共享,多个线程处于可运行状态,但是只允许一个线程在运行,他们通过竞争的方式抢占CPU.可以参考java 进程与线程的区别

线程的状态:
- 新生状态(New):当一个线程被创建一个线程实例后new Thread()或者new Thread(Runnable r),此线程处于新生状态,处于新生状态,线程有自己的内存空间,但该线程没有运行,此时该线程还不是活着的(not Alive)。
- 就绪状态(Runnable):通过线程对象的start()方法启动线程使线程进入就绪状态(runnable),处于就绪状态的线程具备了运行条件(CPU执行资格),但是还没有抢到CPU执行权,不一定会被立即执行。此时线程在线程就绪队列中,等待系统为其分配CPU.等待状态不是执行状态,此时线程是活着的(isAlive=true).
- 运行状态(Running):一旦线程抢到CPU执行权,线程进入运行状态(running),线程run方法才开始执行,运行状态的线程执行自己run方法里面的代码,直到调用其他方法而终止,或者等待某种资源而阻塞,或者完成任务而死亡;如果再给定的时间片内程序没有执行结束,就会被系统暂停当前正在运行的调度程序,回到线程的等待状态。此时线程是活着的(Alive)
- 阻塞状态:(Blocked):通过调用join,sleep,wait或者资源被占用,使线程处于阻塞状态(blocked),处于阻塞状态的线程仍然活着。
- 死亡状态:(Dead):当一个线程的run方法中的代码运行完毕,或被中断,或被异常退出,该线程处于死亡状态。一旦线程进入dead状态,它就再也不能进入一个独立线程的生命周期了,对一个处于dead状态的线程调用start方法,会出现runtime exception异常;处于dead状态的线程不是活着的(Alive)
线程的方法和属性:
- 优先级(priority):每一个线程都有一个优先级。默认优先级是5,优先级最高是10;优先级高的线程并不一定比优先级低的线程执行的机会高,只是执行的机率高;默认一个线程的优先级和创建他的线程优先级相同;setPriority(Thread.MAX_PRIORITY)方法来设置线程的优先级。
- sleep(long millis)/sleep(long millis, int nanos)线程休眠:使当执行的线程休眠指定时间。作用:保持对象锁,让出CPU,调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留一定的时间给其他线程执行的机会;
- Thread.yield():让出CPU的执行权,暂停当前执行的线程对象,让同等优先级的线程运行。稍微的释放执行权一会儿,时间不会很长。
- Thread.join():用来临时加入线程执行,抢夺CPU执行权。例如:当A线程执行到B线程的Join方法时,A就会等待,等B线程执行完之后,A线程才会执行。
object.wait():用在同步中,如果不在锁中使用会抛出IllegalMonitorStateException异常。使线程处于阻塞状态,是线程进入等待池中,释放锁,释放执行权
- object.notify()/notifyAll():唤醒在当前对象等待池中等待的第一个线程/所有线程。notify()/notifyAll()也必须拥有相同对象锁,否则也会抛出IllegalMonitorStateException异常。
Synchronizing Block:机锁具有独占性、一旦被一个Thread持有,其他的Thread就不能再拥有(不能访问其他同步方法),方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。
下面给出上面方法的测试代码:
yield(),join(),priority属性的测试,其它方法不测试了,在是我的文章里面可以看到:
设计两个线程,一个线程为主线程,一个线程Thread-0:
代码:没有用Join方法主线程和Thread-0交替的执行。大家都知道,这里不测试了。但是用了join方法大家看效果.
join方法的源码:

* Waits at most {@code millis} milliseconds for this thread to
* die. A timeout of {@code 0} means to wait forever.
*
* <p> This implementation uses a loop of {@code this.wait} calls
* conditioned on {@code this.isAlive}. As a thread terminates the
* {@code this.notifyAll} method is invoked. It is recommended that
* applications not use {@code wait}, {@code notify}, or
* {@code notifyAll} on {@code Thread} instances.
*
* @param millis
* the time to wait in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
// 加锁当前线程
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
//A线程是start,在运行中
while (isAlive()) {
//main线程等待
wait(0);
}
} else {
//join(timeOut)的情况
while (isAlive()) {
//根据当前timeout的时间-now 是否<=0进行判断,主线程是否继续阻塞等待
long delay = millis - now;
//等待超时时间到了,则主线程不阻塞了,等待结束
if (delay <= 0) {
break;
}
wait(delay);
//子线程从循环开始到现在运行的时间
now = System.currentTimeMillis() - base;
}
}
}

给一个例子来理解:

package concurrentMy.joins; /**
*
* @author Administrator
*
* main 线程 和 A线程,A线程是main线程创建并且启动的,main线程优先级比较高,正在执行;
* 这个时候main线程调用A.join()之后,main线程一直等待,直到A线程运行完毕,main线程才运行
*
*/
class ThreadA extends Thread { public ThreadA(String name){
super(name);
} @Override
public void run() {
、
for (int i = 0; i < 20; i++) {
// 复写父类的toString方法, 返回该线程的字符串表示形式,包括线程名称、优先级和线程组。
// Thread[Thread-1,5,main]默认的优先级为5,优先级从1-10
System.out.println(Thread.currentThread().getName() + "-" + i); }
} } public class JoinDemo { /**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
ThreadA A = new ThreadA("线程A");
A.start();
A.join(); //A线程加入到“main线程”中,main线程一直等待,直到A线程执行完毕,main线程才运行
System.out.println(Thread.currentThread().getName() + "执行");
System.out.println(Thread.currentThread().getName() + "执行终止"); } }

输出结果:

线程A-0
线程A-1
线程A-2
线程A-3
线程A-4
线程A-5
线程A-6
线程A-7
线程A-8
线程A-9
线程A-10
线程A-11
线程A-12
线程A-13
线程A-14
线程A-15
线程A-16
线程A-17
线程A-18
线程A-19
main执行
main执行终止

代码运行整个过程如下图:

例子2,优先级测试

package com.lp.ecjtu.Thread;
/**
*
* @author Administrator
* 当A线程执行到B线程的Join方法时,A就会等待,等B线程执行完之后,A线程才会执行
* Join方法可以用来临时加入线程执行
*/
class Join implements Runnable{ @Override
public void run() {
for(int i=0;i<20;i++){
//复写父类的toString方法, 返回该线程的字符串表示形式,包括线程名称、优先级和线程组。
//Thread[Thread-1,5,main]默认的优先级为5,优先级从1-10
System.out.println(Thread.currentThread().toString()+"-"+i); }
} }
public class JoinDemo { /**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
Join join = new Join();
Thread t1 = new Thread(join);
Thread t2 = new Thread(join);
t2.setPriority(Thread.MAX_PRIORITY);//设置线程的优先级的方法
t1.start();
t2.start(); } }

输出结果:
Thread[Thread-1,10,main]-0
Thread[Thread-1,10,main]-1
Thread[Thread-1,10,main]-2
Thread[Thread-1,10,main]-3
Thread[Thread-1,10,main]-4
Thread[Thread-1,10,main]-5
Thread[Thread-1,10,main]-6
Thread[Thread-0,5,main]-0
Thread[Thread-1,10,main]-7
Thread[Thread-1,10,main]-8
Thread[Thread-0,5,main]-1
Thread[Thread-1,10,main]-9
Thread[Thread-1,10,main]-10
Thread[Thread-1,10,main]-11
Thread[Thread-1,10,main]-12
Thread[Thread-1,10,main]-13
Thread[Thread-1,10,main]-14
Thread[Thread-1,10,main]-15
Thread[Thread-1,10,main]-16
Thread[Thread-1,10,main]-17
Thread[Thread-1,10,main]-18
Thread[Thread-0,5,main]-2
Thread[Thread-1,10,main]-19
Thread[Thread-0,5,main]-3
Thread[Thread-0,5,main]-4
Thread[Thread-0,5,main]-5
Thread[Thread-0,5,main]-6
Thread[Thread-0,5,main]-7
Thread[Thread-0,5,main]-8
Thread[Thread-0,5,main]-9
Thread[Thread-0,5,main]-10
Thread[Thread-0,5,main]-11
Thread[Thread-0,5,main]-12
Thread[Thread-0,5,main]-13
Thread[Thread-0,5,main]-14
Thread[Thread-0,5,main]-15
Thread[Thread-0,5,main]-16
Thread[Thread-0,5,main]-17
Thread[Thread-0,5,main]-18
Thread[Thread-0,5,main]-19
总结:从结果可以看出Thread-1,10,main优先级为10的线程2先执行。
yield方法是正在执行的线程释放执行权,暂停执行一小会儿。这里不测了。。。。。。
java基础知识回顾之java Thread类学习(四)--线程的状态以及转化使用的方法介绍的更多相关文章
- java基础知识回顾之---java String final类普通方法
辞职了,最近一段时间在找工作,把在大二的时候学习java基础知识回顾下,拿出来跟大家分享,如果有问题,欢迎大家的指正. /* * 按照面向对象的思想对字符串进行功能分类. * ...
- java基础知识回顾之java Thread类学习(三)--java线程实现常见的两种方式实现好处:
总结:实现Runnable接口比继承Thread类更有优势: 1.因为java只能单继承,实现Runnable接口可以避免单继承的局限性 2.继承Thread类,多个线程不能处理或者共享同一个资源,但 ...
- java基础知识回顾之java Thread类学习(十)--线程的状态以及转化使用的方法介绍
线程的概述: 线程是程序的多个执行路径,执行调度的单位,依托于进程存在.线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间叫做线程栈,是建立线程的时候由系 ...
- java基础知识回顾之java Thread类--java线程实现常见的两种方式实现Runnable接口(二)
创建线程的第二中方式: /** * 步骤: 1定义类实现Runnable接口 2.实现Runnable接口中的run方法. 3.通过Thread类建立线程对象,并将Run ...
- java基础知识回顾之java Thread类学习(十二)-- 线程中断
官方文档翻译: 如果本线程是处于阻塞状态:调用线程的wait(), wait(long)或wait(long, int)会让它进入等待(阻塞)状态,或者调用线程的join(), join(long), ...
- java基础知识回顾之java集合类-Properties集合
/** java.lang.Object |--java.util.Dictionary<K,V> |--java.util.Hashtable<Object,Obje ...
- java基础知识回顾之java Thread类学习(八)--java.util.concurrent.locks(JDK1.5)与synchronized异同讲解
看API文档介绍几个方法: JDK1.5中提供了多线程的升级解决方案: 特点: 1.将同步synchronized显示的替换成Lock 2.接口Conditio ...
- java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)
*java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时 ...
- java基础知识回顾之java Thread类学习(四)--java多线程安全问题(锁)
上一节售票系统中我们发现,打印出了错票,0,-1,出现了多线程安全问题.我们分析为什么会发生多线程安全问题? 看下面线程的主要代码: @Override public void run() { // ...
- java基础知识回顾之java Thread类学习(七)--java多线程通信等待唤醒机制(wait和notify,notifyAll)
1.wait和notify,notifyAll: wait和notify,notifyAll是Object类方法,因为等待和唤醒必须是同一个锁,不可以对不同锁中的线程进行唤醒,而锁可以是任意对象,所以 ...
随机推荐
- redis哨兵模式下主从切换后,php实现自动切换
redis的哨兵模式,在主服务器挂掉后,会通过选举将对应的从服务器切换为主服务器,以此来达到服务的高可用性. 在业务层面如果主从做了切换可能相对应的服务器IP地址会发生改变,这样会带来程序的的正常运行 ...
- Flink 状态编程
概念 在Flink架构体系中,有状态计算可以说是Flink非常重要的特性之一 Flink优势: 支持高吞吐.低延迟.高性能 支持事件时间Event_time概念 支持有状态计算 有状态计算是指: 在程 ...
- 鲜花:bitset求解高维偏序
书接上回 一维偏序直接做.二维偏序套线段树或归并排序.三维偏序可以树套树或者 CDQ 套树,那四维偏序呢?可以 CDQ 套树套树.那五维偏序呢?可以发现,无论是 CDQ 分治还是树,都很难再继续嵌套, ...
- 关闭 Chrome 浏览器 更新错误 弹窗
1 Chrome使用一段时间后,右上角总会弹出弹窗,并且影响鼠标聚焦,如下图: 2 解决方式: 右键点击 桌面Chrome图表,然后点击属性,按照下图操作: 在 快捷方式--目标 后输入: --di ...
- Linux系统进程
系统进程 [1].进程基本概述 当我们运行一个程序,那么我们将运行的程序叫进程 PS1:当程序运行为进程后,系统会为该进程分配内存,以及进程运行的身份和权限 PS2:在进程运行的过程中,服务器 ...
- 方法的虚分派(virtual dispatch)和方法表(method table)
Java方法调用的虚分派 JUN 2ND, 2013 | COMMENTS 本文通过介绍 Java 方法调用的虚分派,来加深对 Java 多态实现的理解.需要预先理解 Java 字节码和 JVM 的基 ...
- java公式解析器学习与开发(1)
public class Evaluate { public static void main(String[] args) { Stack<String> ops = new Stack ...
- 修复Bug好比钓鱼
作者: Jim Bird 来源: CSDN 发布时间: 2012-09-13 10:43 阅读: 4224 次 推荐: 18 原文链接 [收藏] 英文原文:Fixing a Bug ...
- Redis集群搭建-Docker
使用docker搭建本地集群Redis服务(参考:https://www.cnblogs.com/slowbirdoflsh/p/11633113.html) 环境配置 # 拉取redis镜像 doc ...
- 2023-05 多校联合训练 ZJNU站 正式赛
Scarlett的三元组 有一个长度为 \(n\) 的序列 \(a_1,a_2,\cdots,a_n\),试问有多少个三元组 \((a_i,a_j,a_k)\) 满足: \(1 \le i \lt j ...