zoukankan      html  css  js  c++  java
  • java中线程状态

    刚开始接触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;
        }
    View Code

    通过以上代码了解到,线程有六种状态: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或其子类)。

  • 相关阅读:
    UVA 11806 组合数学+容斥
    Educational Codeforces Round 37 (Rated for Div. 2) G
    java 5 线程池
    团队-象棋游戏-项目进度
    结对-五子棋-测试过程
    结对-五子棋游戏-开发过程
    课后作业-阅读任务-阅读提问-2
    20171006-构建之法:现代软件工程-阅读笔记
    结队-五子棋游戏-项目进度
    团队-象棋游戏-代码设计规范
  • 原文地址:https://www.cnblogs.com/qq931399960/p/10815911.html
Copyright © 2011-2022 走看看