java 面试知识点笔记(九)多线程与并发 下篇

问:线程有哪些状态?java

  1. 新建(new):建立后还没有启动的线程的状态(新建立的线程但尚未调用start方法)
  2. 运行(Runnable):包含Running和Ready(Running线程位于可运行线程中,等待调度选中获取CPU使用权,处于Ready状态的线程位于线程池中,等待调度选中,选中获取CPU时间后变为Running状态)
  3. 无限期等待(Waiting):不会被分配CPU执行时间,须要显式唤醒(notify、notifyAll),如下3个方法会让线程陷入无限期等待状态:
    1. 没有设置Timeout参数的Object.wait()方法
    2. 没有设置Timeout参数的Thread.join()方法
    3. LockSupport.park()方法
  4. 限期等待(Timed Waiting):在必定时间后会由系统自动唤醒(也不会分配CPU执行时间)如下方法会让线程进入限期等待:
    1. Thread.sleep()方法
    2. 设置了Timeout参数的Object.wait()方法
    3. 设置了Timeout参数的Thread.join()方法
    4. ​LockSupport.parkNanos()方法
    5. LockSupport.parkUntil()方法
  5. 阻塞(Blocked):等待获取排他锁(如synchronized同步代码块或方法会出现此状态)
  6. 结束(Terminated):已终止线程的状态,线程已经结束执行(结束状态的线程再调用start方法会抛出java.lang.IllegalThreadStateException异常)

问:sleep和wait的区别?安全

  • sleep是Thread类的方法,wait是Object类的方法
  • sleep方法是能够在任何方法使用
  • wait方法只能在synchronized方法或者synchronized块中使用(由于只有获取锁了才能释放锁)

最主要的本质区别:ide

  1. Thread.sleep只会让出CPU,不会致使锁行为的改变
  2. Object.wait不只让出CPU,还会释放已经占有的同步资源锁

Thread.java中的函数

Object.java中的oop

package interview.thread;

/**
 * wait和sleep的区别
 * @Author: cctv
 * @Date: 2019/5/17 11:49
 */
public class WaitSleepDemo {
    public static void main(String[] args) {
        final Object lock = new Object();
        new Thread(() -> {
            System.out.println("thread A is waiting to get lock");
            synchronized (lock) {
                try {
                    System.out.println("thread A get lock");
                    // 先等B运行起来再到下一步
                    Thread.sleep(20);
                    System.out.println("thread A do wait method");
                    // wait让出CPU和锁 B会抢到锁执行B后再执行A
//                    lock.wait(1000);

                    // sleep不会让出锁 A执行完了以后再执行B
                    Thread.sleep(1000);
                    System.out.println("thread A is done");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        // 先启动A拿到锁,再让B也运行
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            System.out.println("thread B is waiting to get lock");
            synchronized (lock) {
                try {
                    System.out.println("thread B get lock");
                    System.out.println("thread B do wait method");
                    Thread.sleep(10);
                    System.out.println("thread B is done");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();


    }
}

sleep结果:测试

wait结果:线程

 

问:notify和notifyAll的区别?code

首先了解2个概念:对象

  1. 锁池EntryList(一个锁资源被占用以后其余其余线程想要获取锁就进入了阻塞状态,在一个地方等待锁的释放,这个地方就是锁池)
  2. 等待池WaitSet(线程调用某对象的wait方法以后旧进入等待状态,进入等待池中,进入等待吃的线程不会去竞争该对象的锁)

notifyAll会让全部处于等待池的线程所有进入锁池去竞争获取锁的机会blog

notify是随机选择一个处于等待池的线程进入锁池去竞争获取锁的机会

问:yiled的含义?

当调用Thread.yield()函数时,会给线程调度器一个当前线程愿意让出CPU使用的暗示,可是线程调度器可能会忽略这个暗示。

yield并不会让出当前占用的锁

 

问:如何中断线程?

  • 已被抛弃的方法:
    • 经过调用stop()方法中止线程(这种方法太过暴力,并且是不安全的。忽然调用stop中止了线程,致使线程的一些清理工做没法完成,并且会释放锁,可能致使数据不一样步的问题)
    • 经过调用suspend()和resume()方法(缘由和stop相似)
  • 目前使用的方法:
    • 调用interrupt(),通知线程应该中断了
    1. 若是线程处于被阻塞状态,那么线程将马上退出被阻塞状态,并抛出一个InterruptedException异常
    2. 若是线程处于正常活动状态,那么会将该线程的中断标志设置为true。被设置中断标志的线程将继续正常运行,不受影响
    • 须要被调用的线程配合中断:
    1. 在阻塞阻塞线程里,处理InterruptedException异常,并在catch里作好相关清理工做
    2. 在正常运行任务时,常常检查本线程的中断标志位(Thread.currentThread().isInterrupted()方法判断),若是被设置了中断标志就自行中止线程

测试:

package interview.thread;

/**
 * 中断线程demo
 *
 * @Author: cctv
 * @Date: 2019/5/20 10:26
 */
public class InterruptDemo {
    public static void main(String[] args) throws InterruptedException {
        Runnable interruptTask = new Runnable() {
            @Override
            public void run() {
                int i = 0;
                Thread t = Thread.currentThread();
// 加上注释看阻塞状态的处理 去掉注释看工做状态的处理
//                try {
                    while (!t.isInterrupted()) {
//                        Thread.sleep(100);
                        i++;
                        System.out.println(t.getName() + "(" + t.getState() + ") loop " + i);
                    }
                    System.out.println(t.getName() + "(" + t.getState() + ") Thread isInterrupted is true. loop is" + i);
//                } catch (InterruptedException e) {
//                    System.out.println(t.getName() + "(" + t.getState() + ") catch InterruptedException. loop is " + i);
//                }
            }
        };
        Thread t1 = new Thread(interruptTask, "t1");
        System.out.println(t1.getName() + "(" + t1.getState() + ") is new");

        t1.start();
        System.out.println(t1.getName() + "(" + t1.getState() + ") is started");

        Thread.sleep(300);
        t1.interrupt();
        System.out.println(t1.getName() + "(" + t1.getState() + ") is interrupted");

        Thread.sleep(300);
        System.out.println(t1.getName() + "(" + t1.getState() + ") is terminated");
    }
}

相关文章
相关标签/搜索