• java面试题基础之线程篇


    1,什么是进程?什么是线程?

      进程是进程就是操作系统运行的一个程序。

      就是进程的一个执行单元,一条执行路径,是操作系统能够进行运算调度的最小单位

      如果把进程比作一个厂房的话,线程就是流水线。

    2,线程和进程有什么区别?

      进程是运行中的程序,线程是进程的内部的一个执行单元
      进程是资源分配的单元,线程是执行单元
      进程间切换代价大,线程间切换代价小
      进程拥有资源多,线程拥有资源少
      多个线程共享进程的资源

      进程就好比是个爹,管理着众多的线程儿子

    3,如何在Java中实现线程?

      第一种:继承java.lang.Thread类,并重写run()方法

        

        启动线程:创建线程对象并使用start()方法启动线程,此方法会执行run()方法中的代码,并分配线程栈

        

      第二种:实现Runnable接口

        实现该接口有两种创建线程的方式:

        A、单独创建一个类实现接口,再创建线程对象(适用于接口的实现类需要使用多次

           

          

        B、创建匿名内部类对象(适用于接口的实现类只使用一次

        

         C、实现Callable接口,Callable接口的call()方法有返回值(不常用)

        

      

          启动线程,需要借助FutureTask类

          

    4,Java 关键字volatile 与 synchronized 作用与区别?

      修饰的对象不同:

        volatile 用于修饰变量,synchronized修饰代码块或方法

      作用不同:

        volatile 保证数据的可见性和有序性,但它并不能保证数据的原子性。

        synchronized保证数据的互斥性和可见性,并能保证数据的原子性

        原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行

        互斥性:如果将锁加在某个变量上,则每次只有一个线程能够使用该共享数据,直到该线程使用完才会将该共享数据释放,供其它线程使用。

        可见性:是指线程之间的可见性,就是一个线程修改后的结果,其他的线程能够立马知道。 

        volatile不会造成线程堵塞,而synchronized会造成线程堵塞

    5,有哪些不同的线程生命周期?

      线程的生命周期包含6个阶段,包括:新建、就绪、运行、阻塞、等待、销毁。

      新建(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

      就绪(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

      运行(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

      阻塞(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。最常见的就是线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

      等待状态分为以下两种情况:

        无限时等待(Waiting):

          调用Object对象的wait方法,但没有指定超时值。

          调用Thread对象的join方法,但没有指定超时值。

          调用LockSupport对象的park方法

        有限时等待(Timed-Waitng):

          调用带超时参数的 Thread.sleep(long millis) 方法;

          获得 synchronized 隐式锁的线程,调用带超时参数的 Object.wait(long timeout) 方法;

          调用带超时参数的 Thread.join(long millis) 方法;

          调用带超时参数的 LockSupport.parkNanos(Object blocker, long deadline) 方法;

          调用带超时参数的 LockSupport.parkUntil(long deadline) 方法。

      销毁(Terminated):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

      

    6,你对线程优先级的理解是什么?

      每个线程都有一个优先级,取值范围为1-10,且默认优先级为5,优先级越高,获得CUP执行权的几率越高, CPU尽量将执行资源让给线程优先级高的,即线程优先级高的总是会大部分先执行,但是不代表高优先级的线程全部都先执行完再执行低优先级的线程。

      getPriority():获取当前线程的优先级;setPriority():设置优先级级数

      

    7,什么是死锁(Deadlock)?如何分析和避免死锁?

      两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法继续执行,称为死锁。

      产生死锁的必要条件:

        互斥使用(资源独占):一个资源每次只能给一个进程使用(比如写操作)

        占有且等待:进程在申请新的资源的同时,保持对原有资源的占有

        不可抢占:资源申请者不能强行从资源占有者手动夺取资源,资源只能由占有者自愿释放

        循环等待:A等待B占有的资源,B等待C占有的资源,C等待D占有的资源,..........N等待A的资源,形成一个线程等待回路

      分析:

      线程 a率先占有了资源1, 继续运行时需要资源2, 但此时资源2却被线程b占有了, 

      因此只能等待b释放资源2才能够继续运行; 同时,b也需要资源1, 

      它只能等待a释放资源1才能够继续运行, 因此,线程a和b都处于等待状态, 

      谁也无法继续运行,即产生了死锁

      

       解决方式:多线程同步时,保证线程中锁对象的顺序一致。即:将以上代码中b线程的锁对象顺序进行调换。

    8,什么是线程安全?Vector是一个线程安全类吗? 

      当多个线程同时操作堆内存或方法区内存的某个数据时,可能会出现数据不一致的现象,称为线程安全问题。

      Vector在add()等操作上添加了synchronized关键字实现同步,所以是一个线程安全类

    9,Java中如何停止一个线程?

      三种方式:

        A、设置终止标志让run方法停止

        

        

        B、使用stop()方法停止,但此方法已弃用且不是线程安全的

        C、使用interrupt()方法中断线程,但需要isInterrupted()方法配合使用

          

          

    10,什么是ThreadLocal?

        线程局部变量是局限于线程内的变量,属于线程自身所有,不在多个线程间共享。可以保存kv键值对,但是一个ThreadLocal只能保存一个,并且各个线程的数据互不干扰。

    11,sleep()和wait()之间有什么区别?

      sleep()方法是静态方法,通过类直接调用,归属于Tread类;wait()是非静态方法,需要对象的参与才能够调用,归属于Object类

      

      sleep()方法没有释放对象锁;而wait()方法让线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

      wait()只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用 

       sleep()必须捕获异常,而wait()不需要捕获异常 

      

    12,什么是线程饿死,什么是活锁?

      线程饿死是指一个可运行的进程尽管能继续执行,但被调度器无限期地忽视,而不能被调度执行的情况。

      活锁是指是指两个线程优先级相同,都不争资源,就这样一直僵持下去。活锁有可能自行解开,死锁则不能。

      

    13,什么是Java Timer类?如何创建一个有特定时间间隔的任务?

        Timer定时器类,是针对线程实现的定时功能。

        timer.schedule(task, firstTime, period);:指定task任务第一次执行的时间firstTime,以后每隔period毫秒再执行一次

        这个方法还有其它用法:

          timer.schedule(task, time):在指定的时间time,执行任务task

          timer.schedule(task, delay): 延迟delay毫秒后,执行task任务

    14,Java中的同步集合与并发集合有什么区别?

      同步集合和并发集合都能实现线程安全,但同步集合由于存在锁对象的原因,实现的会比并发集合要慢, 这是因为同步集合会把整个Map或List锁起来,而并发集合不会;并发集合实现线程安全是通过使用先进的和成熟的技术像锁剥离。

      

    15,同步方法和同步块,哪个是更好的选择?

        同步方法:使用synchronized修饰方法

        同步块:使用synchronized(object){}进行修饰  

        同步块会更好,因为同步块只针对某些对象, 某种操作下进行锁. 而方法锁有可能出现不相关联的逻辑会有相互影响, 某些情况下对效率有所损失.

    16,什么是线程池? 为什么要使用它?

      线程池:thread pool,是一种线程使用模式,线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。线程池作用就是限制系统中执行线程的数量。  

      为什么要用线程池:

        减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

        可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而导致服务器瘫痪

     

    17,Java中invokeAndWait 和 invokeLater有什么区别?

      可以从事件派发线程中调用invokeLater,却不能从事件派发线程中调用invokeAndWait

    18,多线程中的忙循环是什么?

      忙循环就是程序员用循环让一个线程等待,不像传统方法wait(), sleep() 或 yield() 它们都放弃了CPU控制,

    而忙循环不会放弃CPU,它就是在运行一个空循环。目的是为了保留CPU缓存,在多核系统中,一个等待线程醒来的时候可能会在另一个内核运行,这样会重建缓存。

      目的:避免重建缓存和减少等待重建的时间。

  • 相关阅读:
    centos 7 开放端口
    删除mysql 表中重复的数据
    约瑟夫问题
    Technocup 2020 Elimination Round 3题解
    DISCO Presents Discovery Channel Code Contest 2020 Qual题解
    Comet OJ
    Berlekamp-Massey算法
    CH定理与线性递推
    2020集训队作业板刷记录(一)
    模拟费用流
  • 原文地址:https://www.cnblogs.com/javaisbest/p/12608282.html
Copyright © 2020-2023  润新知