Java线程状态

Java多线程是大多面试场合必问的高频问题,本人在面试美团点评、小红书、金山WPS和海康威视时,被多次问到过 「Java中创建线程有哪几种方式?线程又有哪几种状态?」,在此并针对 「Object类中wait()、notify()和notifyAll()方法的具体使用」 进行一个系统的梳理与总结。

参考答案

Java中创建线程有哪几种方式?
JDK1.5以前,一种是继承Thread类,另一种是实现Runnable接口(推荐使用),两种方式都需要要通过重写run()方法来定义线程行为。
JDK1.5以后,创建线程还有第三种方式:实现Callable接口,该接口中的call()方法可以有返回值,并可以抛出异常。
具体实现代码不再赘述。
Java中线程有哪几种状态?
Java中调用线程的getState()方法可以确定一个线程的当前状态。其中,线程主要有以下6种状态:
  • NEW(新创建)
  • RUNNABLE(可运行)
  • BLOCKED(被阻塞)
  • WAITING(等待)
  • TIMED_WAITING(计时等待)
  • TERMINATED(终止)
其中,线程相关方法与状态关系示意图如下:
方法与状态关系示意图
wait()、notify()和notifyAll()方法的具体使用
Object类有哪些方法?」中介绍了相关方法的主要作用,在此主要介绍这些方法所引起的线程状态的改变情况。
  • wait()方法:线程由RUNNABLE状态到WAITING状态。
  • wait(timeout)方法:线程由RUNNABLE状态到TIMED_WAITING状态。
  • notify()方法:线程由WAITING或TIMED_WAITING状态到RUNNABLE状态。
  • notifyAll()方法:线程由WAITING或TIMED_WAITING状态到RUNNABLE状态。
wait()、notify()和notifyAll()方法为什么定义在Object类中?
wait,notify和notifyAll都是锁级别的操作,所以把他们定义在Object类中是因为锁属于对象。
另外,wait()、notify()和notifyAll()三个方法用于线程通信,要求其只能在synchronized声明的方法或synchronized代码块中使用,否则会报java.lang.illegalMonitor StateException的异常。

扩展阅读——生产者消费者问题

是否涉及多线程的问题?是!生产者和消费者相当于多线程,而店员类似共享数据。
是否涉及共享数据?是,店员处产品数量,故要考虑线程安全的问题,线程同步。
是否涉及线程的通信问题?是,存在生产者与消费者的通信问题,可使用wait()、notify()和notifyAll()来实现。
public class TestProduceConsume {
    public static void main(String[] args) {
        Clerk clerk = new Clerk();
        Producer p1 = new Producer(clerk);
        Consumer c1 = new Consumer(clerk);
        Thread t1 = new Thread(p1);// 生产者线程1
        Thread t2 = new Thread(c1);// 消费者线程1
        Thread t3 = new Thread(p1); // 生产者线程2
        t1.setName(“生产者1”);
        t2.setName(“消费者”);
        t3.setName(“生产者2”);

        t1.start();
        t2.start();
        t3.start();
    }
}

class Producer implements Runnable // 生产者
    private Clerk clerk;

    public Producer(Clerk clerk) {
        this.clerk = clerk;
    }

    public void run() {
        System.out.println(“生产者开始生产产品!”);
        while (true) {
            try {
                Thread.currentThread().sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            clerk.addProduct();
        }
    }
}

class Consumer implements Runnable // 消费者
    private Clerk clerk;

    public Consumer(Clerk clerk) {
        this.clerk = clerk;
    }

    public void run() {
        System.out.println(“消费者开始购买产品!”);
        while (true) {
            try {
                Thread.currentThread().sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            clerk.consumeProduct();
        }
    }
}

class Clerk // 店员 类似共享数据
    private int product;

    public synchronized void addProduct() {
        if (product >= 20) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            product++;
            notifyAll();
            System.out.println(Thread.currentThread().getName() + “:生产”
                    + product);
        }
    }

    public synchronized void consumeProduct() {
        if (product <= 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println(Thread.currentThread().getName() + “:消费”
                    + product);
            product–;
            notifyAll();
        }
    }

本站所有文章均由网友分享,仅用于参考学习用,请勿直接转载,如有侵权,请联系网站客服删除相关文章。若由于商用引起版权纠纷,一切责任均由使用者承担
极客文库 » Java线程状态

Leave a Reply

欢迎加入「极客文库」,成为原创作者从这里开始!

立即加入 了解更多