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块中使用(因为只有获取锁了才能释放锁)

最主要的本质区别:

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

Thread.java中的

Object.java中的

1package interview.thread; 2 3/** 4 * wait和sleep的区别 5 * @Author: cctv 6 * @Date: 2019/5/17 11:49 7 */ 8public class WaitSleepDemo { 9 public static void main(String[] args) { 10 final Object lock = new Object(); 11 new Thread(() -> { 12 System.out.println("thread A is waiting to get lock"); 13 synchronized (lock) { 14 try { 15 System.out.println("thread A get lock"); 16 // 先等B运行起来再到下一步 17 Thread.sleep(20); 18 System.out.println("thread A do wait method"); 19 // wait让出CPU和锁 B会抢到锁执行B后再执行A 20// lock.wait(1000); 21 22 // sleep不会让出锁 A执行完了之后再执行B 23 Thread.sleep(1000); 24 System.out.println("thread A is done"); 25 } catch (InterruptedException e) { 26 e.printStackTrace(); 27 } 28 } 29 }).start(); 30 31 // 先启动A拿到锁,再让B也运行 32 try { 33 Thread.sleep(10); 34 } catch (InterruptedException e) { 35 e.printStackTrace(); 36 } 37 new Thread(() -> { 38 System.out.println("thread B is waiting to get lock"); 39 synchronized (lock) { 40 try { 41 System.out.println("thread B get lock"); 42 System.out.println("thread B do wait method"); 43 Thread.sleep(10); 44 System.out.println("thread B is done"); 45 } catch (InterruptedException e) { 46 e.printStackTrace(); 47 } 48 } 49 }).start(); 50 51 52 } 53}

sleep结果:

wait结果:

问:notify和notifyAll的区别?

首先了解2个概念:

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

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

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

问:yiled的含义?

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

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

问:如何中断线程?

  • 已被抛弃的方法:

    • 通过调用stop()方法停止线程(这种方法太过暴力,而且是不安全的。突然调用stop停止了线程,导致线程的一些清理工作无法完成,而且会释放锁,可能导致数据不同步的问题)
    • 通过调用suspend()和resume()方法(原因和stop类似)
  • 目前使用的方法:

    • 调用interrupt(),通知线程应该中断了
    1. 如果线程处于被阻塞状态,那么线程将立刻退出被阻塞状态,并抛出一个InterruptedException异常
    2. 如果线程处于正常活动状态,那么会将该线程的中断标志设置为true。被设置中断标志的线程将继续正常运行,不受影响
    • 需要被调用的线程配合中断:
    1. 在阻塞阻塞线程里,处理InterruptedException异常,并在catch里做好相关清理工作
    2. 在正常运行任务时,经常检查本线程的中断标志位(Thread.currentThread().isInterrupted()方法判断),如果被设置了中断标志就自行停止线程

测试:

1package interview.thread; 2 3/** 4 * 中断线程demo 5 * 6 * @Author: cctv 7 * @Date: 2019/5/20 10:26 8 */ 9public class InterruptDemo { 10 public static void main(String[] args) throws InterruptedException { 11 Runnable interruptTask = new Runnable() { 12 @Override 13 public void run() { 14 int i = 0; 15 Thread t = Thread.currentThread(); 16// 加上注释看阻塞状态的处理 去掉注释看工作状态的处理 17// try { 18 while (!t.isInterrupted()) { 19// Thread.sleep(100); 20 i++; 21 System.out.println(t.getName() + "(" + t.getState() + ") loop " + i); 22 } 23 System.out.println(t.getName() + "(" + t.getState() + ") Thread isInterrupted is true. loop is" + i); 24// } catch (InterruptedException e) { 25// System.out.println(t.getName() + "(" + t.getState() + ") catch InterruptedException. loop is " + i); 26// } 27 } 28 }; 29 Thread t1 = new Thread(interruptTask, "t1"); 30 System.out.println(t1.getName() + "(" + t1.getState() + ") is new"); 31 32 t1.start(); 33 System.out.println(t1.getName() + "(" + t1.getState() + ") is started"); 34 35 Thread.sleep(300); 36 t1.interrupt(); 37 System.out.println(t1.getName() + "(" + t1.getState() + ") is interrupted"); 38 39 Thread.sleep(300); 40 System.out.println(t1.getName() + "(" + t1.getState() + ") is terminated"); 41 } 42}

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Java线程的6种状态及切换(透彻讲解)

Java中线程的状态分为6种。1\.初始(NEW):新创建了一个线程对象,但还没有调用start()方法。2\.运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的