刚开始接触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. [Nginx]子目录反向代理kibana并添加basic认证

    背景 服务器ip:192.168.1.2 安装软件 nginx kibana(默认端口5601) 实现方案:访问http://192.168.1.2/kibana 即可访问到kibana后端,同时需要 ...

  2. python zip用法

    import requests url = "https://magi.com/search" querystring = {"q":"堕却乡&quo ...

  3. Codeforce Round #424

    A 略 B 略 C: 先对Ai数列预处理前缀和 然后把Bi的每个都加一次 最终得到的结果为ans[sum]++; 最后如果有一个ans[sum]>=k即满足所有K个条件就输出(注意!!前缀和要进 ...

  4. 配置LANMP环境(6)-- 安装APACHE与PHP配置

    一.安装 Apache 2.4 安装:默认安装2.4版本 yum install httpd 修改配置 vim /etc/httpd/conf/httpd.conf 42行80端口改为 8080查看行 ...

  5. Easy UI 入门

    Easy UI常用于企业级开发的UI和后台开发的UI,比较重. 以下组件中的加载方式,属性和事件,方法和组件种类并不全,只是作为参考和入门学习. 1.Draggable(拖动)组件 不依赖其他组件 1 ...

  6. CSS基础学习-13.CSS 浮动

    如果前一个元素设置浮动属性,则之后的元素也会继承float属性,我觉得这里说是继承不太对,可以理解为会影响到之后的元素,所以在设置浮动元素之后的元素要想不被影响就需要清除浮动.元素设置左浮动,则清除左 ...

  7. Java 解析自定义XML文件

    这里我用 maven项目 作为 演示 配置pom.xml文件 完整的pom.xml文件信息 <?xml version="1.0" encoding="UTF-8& ...

  8. php类知识----特别用法

    spl_autoload_register注册 <?php #spl_autoload_register-----这个例子是用来打印实例化类的类名 function thereisagameof ...

  9. bat批处理文件

    将某个文件夹中的所有txt文件合并到a.txt中,如果文件比较多的话,手动会很费时,编写程序也很麻烦,这个时候就可以用批处理文件,如下: type *.txt > a.txt 把上面这行粘贴到新 ...

  10. JZOJ 5988 珂学计树题 (Burnside引理)

    什么神题a-没学过Burnside引理a学了也做不来系列-考场没怎么看这题,上最后十分钟打了样例就溜了-然后这题爆0了. Here CODE #include <cctype> #incl ...