刚开始接触java时,就觉得多线程是一个障碍,不容易理解,当时选择了跳过,不过工作一段时间后,发现这块还是需要深入研究一下的,及时平时工作中不使用多线程,但一定会使用web容器,比如tomcat,也是会接触到多喜爱能成,况且现在工作中也是需要使用到多线程。首先从简单的开始,了解线程的状态,查看Thread源码,与getState方法在一起的有个枚举State,其包含了线程的所有状态

JDK版本为1.8

public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW, /**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE, /**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED, /**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING, /**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING, /**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}

通过以上代码了解到,线程有六种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED

根据个人理解,简单列出了各状态之间的转换

NEW到RUNNABLE状态不可回退

RUNNABLE到TERMINATED状态不可回退

代码验证NEW,RUNNABLE和TERMINATED状态

package com.demo;

public class ThreadTest {

    public static void main(String[] args) {
Thread t = new Thread() { @Override
public void run() {
System.out.println("run");
}
}; System.out.println(t.getState()); // NEW,还未调用start方法
t.start();
System.out.println(t.getState()); // RUNNABLE,调用了start方法,但线程还未结束 try {
// 等待线程结束,其实休眠毫秒级应该就可以结束
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t.getState());// TERMINATED,线程结束 }
}

输出结果

 验证BLOCK与WAITING状态

package com.demo;

public class ThreadTest {

    public static void main(String[] args) {

        Runnable r = new Runnable() {

            @Override
public void run() {
synchronized (this) {
try {
Thread.sleep(50000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}; Thread t1 = new Thread(r, "Thread1");
Thread t2 = new Thread(r, "Thread2"); // 优先级数字范围为1到10,默认5,数字越小,优先级越高
t1.setPriority(5);
t2.setPriority(8); t1.start();
t2.start(); }
}

打包成jar包,java -cp thread.jar com.demo.ThreadTest

ps找到对应的pid

Thread1优先执行,获取到锁,调用了sleep方法,处于TIMED_WAITING状态,Thread2未获取到锁,处于BLOCKED状态

将上述测试中Thread.sleep方法改为this.wait()

jstack查看结果

调用wait方法释放了锁,所以两条线程依次进入到synchronized代码块,处于WAITING状态,只有等到被notify或者notifyAll才能恢复为RUNNABLE状态,而有参的sleep或者wait等方法,则可以在制定的时间过后,自动变为RUNNABLE状态。

验证TIMED_WAITING状态

向this.wait方法传递参数

jstack查看结果

两条线程均处于TIMED_WAITING状态,说明它们同样都获取到了锁,wait方法,无论是否带参数,都会释放锁,但sleep不会释放锁

 yield方法

不推荐使用,按照源码中注释所述,该方法使当前线程释放锁,释放对处理器的占用。但很少有适合使用该方法的场景,在debug或者测试或者设计并发控制结构,如juc包中的数据结构时可能会比较有用,不需要特别的关注该方法

暂停(suspend),重新开始(resume),销毁(destory)由于死锁问题,已经被标记为过时,不推荐使用

中断(interrput)

该方法在一些地方使用时,会抛出异常,比如在一个由于sleep方法被阻塞的线程上使用该方法,将抛出InterruptedException异常,具体可查看源码。

interrput方法并非真正的中断了线程,只是在该线程上设置了一个中断标志,如果需要中断线程中的后续操作,还需要在线程内部写一些代码配合使用

package com.demo;

public class ThreadTest {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable(), "mythread");
t.start();
t.interrupt();
}
} class MyRunnable implements Runnable {
int j = 0; @Override
public void run() {
System.out.println("中断状态:" + Thread.currentThread().isInterrupted());
System.out.println("线程状态:" + Thread.currentThread().getState());
for (int i = 0; i < 100000; i++) {
j++;
}
System.out.println(j);
} }

输出结果

可以看出,在for循环还未执行的时候,线程已经处于中断状态,但并未真正的中断,for循环已经被执行了,因此,interrupt方法只是设置了中断状态标志为true,并未真正的中断线程。可以根据线程状态,做一些操作,来达到类似中断线程的效果

如上代码,在for循环中,加入判断条件

输出结果

可以看出,线程处于中断状态,for循环的j没有累加。为了看的比较真切,可以在中断之前,休眠一段时间,比如sleep 3毫秒,输出结果

为什么wait和notify,notifyAll方法被定义到了Object中,而不是在Thread中?

根据wait,notify,notifyAll方法源码注释可知,这几个方法必须在synchronized内部使用,而synchronized使用的锁是任意的,我们在锁上调用wait和notify方法来完成线程间通信,也即是说,对于所有对象,wait和notify以及notifyAll方法都必须是可以使用的,所有对象都可使用的方法,那就要放到Object中了,如果将wait和notify方法放入到Thread线程类中,那么锁的类型就极大的被缩减到一种(必须是Thread或其子类)。

java中线程状态的更多相关文章

  1. java中线程状态-死亡

    线程死亡: 线程会以如下3种方式结束,结束后就处于死亡状态. 1.run()或call()方法执行完成,线程正常结束. 2.线程抛出一个未捕获的Exception或Error 3.直接调用该线程的st ...

  2. Java多线程 - 线程状态

    转自: http://www.cnblogs.com/lwbqqyumidi/p/3804883.html 一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的 ...

  3. JAVA中线程同步方法

    JAVA中线程同步方法 1  wait方法:         该方法属于Object的方法,wait方法的作用是使得当前调用wait方法所在部分(代码块)的线程停止执行,并释放当前获得的调用wait所 ...

  4. 多线程(三) java中线程的简单使用

    java中,启动线程通常是通过Thread或其子类通过调用start()方法启动. 常见使用线程有两种:实现Runnable接口和继承Thread.而继承Thread亦或使用TimerTask其底层依 ...

  5. 沉淀再出发:java中线程池解析

    沉淀再出发:java中线程池解析 一.前言 在多线程执行的环境之中,如果线程执行的时间短但是启动的线程又非常多,线程运转的时间基本上浪费在了创建和销毁上面,因此有没有一种方式能够让一个线程执行完自己的 ...

  6. Java多线程并发03——在Java中线程是如何调度的

    在前两篇文章中,我们已经了解了关于线程的创建与常用方法等相关知识.接下来就来了解下,当你运行线程时,线程是如何调度的.关注我的公众号「Java面典」了解更多 Java 相关知识点. 多任务系统往往需要 ...

  7. java中线程分两种,守护线程和用户线程。

    java中线程分为两种类型:用户线程和守护线程. 通过Thread.setDaemon(false)设置为用户线程: 通过Thread.setDaemon(true)设置为守护线程. 如果不设置次属性 ...

  8. java中线程机制

    java中线程机制,一开始我们都用的单线程.现在接触到多线程了. 多线性首先要解决的问题是:创建线程,怎么创建线程的问题: 1.线程的创建: 四种常用的实现方法 1.继承Thread. Thread是 ...

  9. Java中线程的使用 (2)-多线程、线程优先级、线程睡眠、让步、阻塞

    Java中线程的使用 (2)-多线程.线程优先级.线程睡眠.让步.阻塞 (一)多线程使用方法 说明:创建每个新的线程,一定要记得启动每个新的线程(调用.start()方法) class Xc3 ext ...

随机推荐

  1. 创建LEANGOO项目

    转自:https://www.leangoo.com/leangoo_guide/leangoo_guide_create_project.html#toggle-id-3 一个项目包括多个看板和多名 ...

  2. 链接进入react二级路由,引发的子组件二次挂载

    这个问题很怪,我两个二级路由从链接进入的时候,会挂载两次子组件. 从链接进入,是因为新页面在新标签页打开的. 有子组件是因为公共组件提取 同样的操作,有一些简单的二级路由页面,就不会挂载两次. 讲道理 ...

  3. SQL 多表查询展示

    ########################多表########################SELECT COUNT(*) FROM MEMBER1 A; 查询出来的结果为43行数据: SEL ...

  4. jvm出现OutOfMemoryError时处理方法/jvm原理和优化参考

    The heap stores all of the objects created by your java program.The heap's contents is monitored by ...

  5. odoo xml中添加数据的数字代表含义

    参考原文:https://alanhou.org/odoo12-import-export-data/ <?xml version="1.0"?> <odoo n ...

  6. Spinner simpleAdapte适配器 下拉列表

    public class MainActivity extends AppCompatActivity { private TextView text; private Spinner spinner ...

  7. Hadoop_08_客户端向HDFS读写(上传)数据流程

    1.HDFS的工作机制: HDFS集群分为两大角色:NameNode.DataNode (Secondary Namenode) NameNode负责管理整个文件系统的元数据 DataNode 负责管 ...

  8. Zookeeper01——zk的基本信息和安装

    一.Zookeeper的基本信息 1.1背景 无论在前面,我们学习hdfs,还是学习redis集群,我们都会使用到一个zookeeper进行选举.这导致了Redis的产生. 我们知道,在先前我们使用Z ...

  9. LoadRunner(1)

    性能测试:HP LoadRunner11 一.初步概念: 1.功能测试:测试产品的功能是否满足功能需求. 如:ATM取款(在线取款)是否成功或转账操作是否成功 -- 一个用户 2.性能测试:测试产品的 ...

  10. java 学习笔记(三)ZooKeeper集群搭建实例,以及集成dubbo时的配置 (转)

    ZooKeeper集群搭建实例,以及集成dubbo时的配置 zookeeper是什么: Zookeeper,一种分布式应用的协作服务,是Google的Chubby一个开源的实现,是Hadoop的分布式 ...