java程序员面试(八)

多线程

  1. 什么是多线程?它与进程有什么区别?为什么要使用多线程。
  • 线程是指程序在执行过程中,能够执行程序代码的一个执行单元。
  • 在java语言中,线程有4种状态:运行、就绪、挂起和结束。
  • 进程是指一段正在执行的程序。而线程有时也被称为轻量级进程,它是程序执行的最小单元,一个进程可以拥有多个线程,各个线程共享程序的内存空间(代码段、数据段、堆空间)及一些进程级的资源,但是各个线程有自己的栈空间。
  • 多线程的使用带来的好处:

    • 使用多线程可以减少程序的响应时间。
    • 与进程相比,线程的创建和切换开销更小。
    • 多CPU或多核计算机本身就具有执行多线程的能力,充分利用计算机资源。
    • 多线程能简化程序的结构,使程序便于理解和维护。
  1. 同步和异步有什么区别?
  • 数据共享情况下,多个线程需要访问同一个资源时,需要以某种顺序来确保该资源在某一时刻只能被一个 线程访问,这种情况下就必须对数据进行同步。同步机制能够保证资源的安全。
  • 要实现同步操作,必须要获得每一个线程对象的锁。获得它可以保证在同一时刻只有一个线程能够进入临界区(访问互斥资源的代码块),并且在这个锁被释放之前,其他线程就不再能进入这个临界区。如果还有其他线程想要获得该对象的锁,只能进入等待队列等待。只有当拥有该对象锁的线程退出临界区时,锁才会被释放,等待队列中优先级最高的线程才能获得该锁,从而进入共享代码区。
  • 实现同步的方式有两种:一种是利用同步代码块来实现同步;另一种是利用同步方法来 实现同步。
  • 异步与非阻塞类似,由于每个线程都包含了运行时自身所需要的数据或方法,因此,在进行输入输出处理时,不必关心其他线程的状态或行为,也不必等到输入输出处理完毕才返回。当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回 时,就应该使用异步编程,异步能够提高程序的效率。
  1. 如何实现Java多线程?
  • Java虚拟机允许应用程序并发地运行多个线程。在Java语言中,多线程的实现一般有以下3种方法,

    • 继承Thread类,重写run()方法。Thread本质上也是实现了Runnable接口的一个实例,它代表一个 线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()方法。start()方法是一个native(本地),它将启动一个新的线程,并执行run()方法。调用start()方法并不是立即执行多线程代码,而是使得该线程变为可运行态,什么时候运行 多线程代码是由操作系统决定的。
    • 实现Runnable接口,并实现该接口的run()方法。 自定义类并实现Runnable接口,实现run()方法;创建Thread对象,用实现Runnable接口的对象作为参数实例化该Thread对象;调用Thread的start()方法。其实,不管是通过继承Thread类还是通过使用Runnable接口来实现多线程的方法,最终还是通过Thread的对象的API来控制线程的。
    • 实现Callable接口,重写call()方法。
  1. run()方法和start()方法有什么区别
  • 系统通过调用线程类的start()方法来启动一个线程,此时线程处于就绪状态,而非运行状态,也就意味着这个线程可以被JVM来调度执行。
  • 在调度过程中,JVM通过调用线程类的run()方法来完成实际的操作,当run()方法结束后,此线程就会终止。
  • 如果直接调用线程类的run()方法,这会被当作一个普通函数调用,程序仍然只有主线程这个线程,也就是时说,start()方法能够异步地调用run()方法,但是直接调用run()方法却是同步的,因此也无法达到多线程的目的。
  • 只有通过调用线程类的start()方法才能真正达到多线程的目的。
  1. 多线程同步的实现方法有哪些?
  • 当使用多线程访问同一个资源时,非常容易出现线程安全的问题。Java主要提供了3种实现同步机制的方法:

    • synchronized关键字 在Java语言中,每个对象都有一个对象锁与之相关联,该锁表明对象在任何时候只允许被一个线程所拥有,当一个线程调用对象的一段synchronized代码时,需要先获取这个锁,然后去执行相应的代码,执行结束后,释放锁。
    • sychronized块。sychronized块既可以把任意的代码声明为sychronized,也可以指定上锁的对象,有非常高的灵活性。
  • wait()方法与notify()方法

    • 当使用synchronized来 修饰某个共享资源时,如果线程A1在执行synchronized代码,另外一个线程A2也要同时执行同一对象sychronized代码时,线程A2将要等到线程A1执行完成后,才能执行。在这种情况下可以使用wait()方法和notify()方法。
    • 在synchronized来修饰某个共享资源时,线程可以调用对象的wait()方法,释放对象锁,进入等待状态,并且可以调用notify()方法或notifyAll()方法通知正在等待的其他线程。notify()方法仅唤醒一个线程并允许他去获得锁,notifyAll()方法唤醒所有等待这个对象的线程并允许他们去获得锁 。
  • Lock

    • JDK5 新增加了Lock接口及它的一个实现类ReentrantLock(重入锁),Lock也可以用来实现多线程的同步。
    • lock() 以阻塞的方式获取锁,如果获取到了锁,立即返回;如果别的线程持有锁,当前线程等待,直到获取锁后返回。
    • tryLock() 以非阻塞的方式获取锁。只是尝试性的去获取一下锁,如果获取到锁。立即返回true,否则立即返回false。
    • tryLock(long timeout,TimeUnit unit)。如果获取了锁,立即返回true,否则会等待参数给定的时间单元,在等待的过程中,如果获取了锁,就返回true,如果等待超时,返回false。
    • lockInterruptibly() 如果获取了锁,立即返回;如果没有获取锁,当前线程处于休眠状态,直到获得锁,或者当前线程被别的线程中断。它与lock()方法最大的区别在于如果lock()方法获取不到锁,会一直处于阻塞状态,且会忽略interrupt()方法。
  1. sleep()方法与wait()方法有什么区别?

    • sleep()是使线程暂停执行一段时间的办法。
    • wait()也是使线程暂停执行的方法。
    • 原理不同。 sleep()方法是Thread类的静态方法,是线程用来控制自身流程的,它会使此线程暂停执行一段时间,而把执行机会让给其他线程,等到计时时间一到,此线程会自动苏醒。。wait()是Object类的方法,用于线程间通信。这个方法会使当前拥有该对象锁的进程等待,直到其他线程调用notify()方法时才醒来。与wait配套的方法还有notify方法和notifyAll方法。
    • 对锁的处理机制不同,sleep不会释放锁,wait方法是会释放锁。
    • 使用区域不同。wait()具有特殊意义,因此它必须放在同步控制方法或者同步代码块语句中使用,而sleep()方法则可以在任何地方使用。
  2. sleep()方法和yield()方法有什么区别?
  3. 终止线程的方法有哪些
  4. synchronized与Lock有什么区别?
  5. 什么是守护线程
  6. join()方法的作用是什么?

本文链接:

https://heyzen.club/index.php/J/307.html
1 + 5 =
快来做第一个评论的人吧~