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

Wesley13
• 阅读 538

问:线程有哪些状态?

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中的

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

Object.java中的

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

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结果:java 面试知识点笔记(九)多线程与并发 下篇

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

问: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()方法判断),如果被设置了中断标志就自行停止线程

测试:

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");
    }
}

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

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

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
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
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3天前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
2年前
java 线程及线程池
说明:线程共包括以下5种状态。1. 新建状态(New):线程对象被创建后,就进入了新建状态。例如,ThreadthreadnewThread()。2. 就绪状态(Runnable):也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread
Wesley13 Wesley13
2年前
Java线程的6种状态及切换(透彻讲解)
Java中线程的状态分为6种。1\.初始(NEW):新创建了一个线程对象,但还没有调用start()方法。2\.运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的
Wesley13 Wesley13
2年前
4、jstack查看线程栈信息
1、介绍利用jps、top、jstack命令找到进程中耗时最大的线程,以及线程状态等等,同时最后还可以显示出死锁的线程查找:FoundoneJavaleveldeadlock即可1、jps获得进程号!(https://oscimg.oschina.net/oscnet/da00a309fa6
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
5个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这