美文网首页
线程的5种状态

线程的5种状态

作者: migill | 来源:发表于2019-12-11 19:26 被阅读0次

线程从创建、运行到结束总是处于下面五个状态之一:新建状态、就绪状态、运行状态、阻塞状态及死亡状态。

新建状态(New)
当用new操作符创建一个线程时,例如new Thread(),线程还没有开始运行,此时线程处于新建状态。

就绪状态(Runnable)
线程对象被创建后,当线程对象调用start()方法,从而来启动该线程。处于就绪状态的线程,随时可能被CPU调度执行。

处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程。因为在单CPU的计算机系统中,不可能同时运行多个线程,一个时刻仅有一个线程处于运行状态。因此此时可能有多个线程处于就绪状态。对多个处于就绪状态的线程是由Java运行时系统的线程调度程序(thread scheduler)来调度的。

运行状态(Running)
当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法。需要注意的是,线程只能从就绪状态进入到运行状态。

阻塞状态(Blocked)
所谓阻塞状态是正在运行的线程没有运行结束,暂时让出CPU,这时其他处于就绪状态的线程就可以获得CPU时间,进入运行状态。

线程运行过程中,可能由于各种原因进入阻塞状态:

  • 线程通过调用sleep方法进入睡眠状态;
  • 线程试图得到一个锁,而该锁正被其他线程持有;
  • 线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
  • 线程在等待某个触发条件;

死亡状态(Dead)
run()方法执行结束,线程正常退出。
为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false.

线程中经常用到的几个方法

Thread.sleep(long millis):一定是当前线程调用此方法,当前线程进入阻塞,但不释放对象锁,millis后线程自动苏醒进入可运行状态。作用:给其它线程执行机会的最佳方式。

Thread.yield():使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。cpu会从众多的可执行态里选择,也就是说,当前也就是刚刚的那个线程还是有可能会被再次执行到的,并不是说一定会执行其他线程而该线程在下一次中不会执行到了。

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + " 执行 " + i);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (i == 3) {
                        System.out.println(Thread.currentThread().getName() + " 让出CPU ");
                        Thread.yield();
                    }
                }
                System.out.println(Thread.currentThread().getName() + " 执行结束 ");
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + " 执行 " + i);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (i == 3) {
                        System.out.println(Thread.currentThread().getName() + " 让出CPU ");
                        Thread.yield();
                    }

                }
                System.out.println(Thread.currentThread().getName() + " 执行结束 ");
            }
        });

        t1.setName("Thread-1");
        t2.setName("Thread-2");
        t1.start();
        t2.start();
        System.out.println(Thread.currentThread().getName() + " 执行结束 ");
    }
}
运行结果

t.join()/t.join(long millis):任何地方当调用了t.join(),就必须要等待线程t执行完毕后,才能继续执行其他线程。这里其实是运用了Java中最顶级对象Object提供的方法wait()。wait()方法用于线程间通信,它的含义是通知一个线程等待一下,让出CPU资源,注意这里是会放弃已经占有的资源的。直到t线程执行完毕,再调用notify()唤醒当前正在运行的线程。

public class ThreadTest {
   public static void main(String[] args) throws InterruptedException {
       Thread t1 = new Thread(new Runnable() {
           @Override
           public void run() {
               for (int i = 0; i < 5; i++) {
                   System.out.println(Thread.currentThread().getName() + "  ");
                   try {
                       Thread.sleep(100);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
               System.out.println(Thread.currentThread().getName() + " 执行结束 ");
           }
       });
       Thread t2 = new Thread(new Runnable() {
           @Override
           public void run() {
               for (int i = 0; i < 5; i++) {
                   System.out.println(Thread.currentThread().getName() + "  ");
                   try {
                       Thread.sleep(100);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }

               }
               System.out.println(Thread.currentThread().getName() + " 执行结束 ");
           }
       });

       t1.setName("Thread-1");
       t2.setName("Thread-2");
       t1.start();
       t1.join();
       t2.start();
       t2.join();
       System.out.println(Thread.currentThread().getName() + " 执行结束 ");
   }
运行结果

obj.wait():当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout)timeout时间到自动唤醒。
obj.notify():唤醒正在等待对象监视器的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。该方法不释放锁的。

public class ThreadDemo {
    private volatile static List<String> list = new ArrayList<>(20);

    public void add(int i) {
        list.add("元素" +i);
    }

    public int size() {
        return list.size();
    }

    public static void main(String[] args) {
        final ThreadDemo wDemo = new ThreadDemo();
        final Object obj = new Object();

        Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    synchronized (obj) {
                        System.out.println("已进入t1");
                        for (int i = 0; i < 6; ++i) {
                            wDemo.add(i);
                            System.out.println("当前的线程:" + Thread.currentThread().getName() + "添加了一个元素。。");
                            Thread.sleep(200);
                            if (wDemo.size() == 5) {
                                obj.notify();
                                System.out.println("已发出通知!");
                            }
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "t1");

        Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {
                synchronized (obj) {
                    System.out.println("已进入t2");
                    if (wDemo.size() != 5) {
                        try {
                            System.out.println("t2释放锁前");
                            obj.wait();
                            System.out.println("t2释放锁后");
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("t2线程收到通知");
                }
            }
        }, "t2");
        t2.start();
        t1.start();
    }
}
运行结果

wait和notify必须配合synchronized使用,而且wait必须在notify前用,wait后就会进入notify所在的线程,notify后唤醒wait所在的线程,但是wait所在的线程仍然没有获取锁,需要等待notify所在的线程释放锁。

相关文章

  • java多线程

    线程六种状态 New:尚未启动的线程的线程状态(new Thread) Runnable:可运行线程的线程状态,等...

  • 2.线程状态

    线程的状态 New:尚未启动的线程的线程状态 Runnable:调用start,可运行线程的线程状态,但是实际上不...

  • 4 多线程

    多线程 线程的状态 新状态 就绪状态 运行状态 阻塞状态 终止状态 线程的优先级 1--10, 默认为5,但线程优...

  • java多线程基本概念(一)

    线程生命周期 说明线程工共包含5个状态: 新建状态new:调用线程构造方法创建线程后,线程进入新建状态; 就绪状态...

  • 【问答】Java多线程

    线程的状态,画一个线程的生命周期状态图 线程状态:NEW,未启动的线程;RUNNABLE,运行中,包括就绪状态和运...

  • 一、线程的状态转换

    线程的状态转换 线程的6个状态 New 线程刚创建的状态; Runnable 调用start()后的状态,可以对应...

  • 线程的学习总结

    我打算从线程得生命周期开始总结多线程: 线程的生命周期: 新建状态:线程对象创建之后,线程进入新建状态. 就绪状态...

  • 线程状态

    线程状态 线程一共有五种状态,理解和掌握线程状态,有利于更好地掌握线程同步相关的知识。 新建状态(New),新建了...

  • java多线程总结2

    结束线程 线程的状态 新建(new):线程被创建时短暂处于该状态,字后调度器将把线程转变为就绪状态或阻塞状态。 就...

  • 线程相关

    1、线程状态 NEW 新建状态,线程创建且没有执行start方法时的状态 RUNNABLE 可运行状态,线程已经启...

网友评论

      本文标题:线程的5种状态

      本文链接:https://www.haomeiwen.com/subject/uecagctx.html