• Java面试专题-多线程篇(1)


    开篇介绍

    大家好,公众号【Java极客思维】近期会整理一些Java高频面试题分享给小伙伴,也希望看到的小伙伴在找工作过程中能够用得到!本章节主要针对Java一些多线程高频面试题进行分享。

    Q1:

    线程 和 进程有什么区别?

    进程:

    进程是程序运行资源分配的最小单位。进程内部有多个线程,会共享这个进程中的资源。

    线程:

    线程是CPU调度的最小单位。必须依赖进程而存在。

    特点:

    • 线程的划分尺度小于进程,这使得多线程拥有高并发性;

    • 进程在运行时各自内存单元相互独立,线程之间内存共享;

    • 多线程开发可以拥有更好的性能和用户体验。

    (注意:多线程开发对于其他程序是不友好的,占据大量CPU资源。)

    Q2:

    如何安全的终止线程?

    理解中断:

    线程自然终止:自然执行完 或 抛出未处理的异常。Java线程是协作式工作,而非抢占式工作;

    • stop()、resume()、suspend()三个方法已经在后续的jdk版本已过时,不建议使用;

      • stop()方法:会导致线程不正确释放资源;

      • suspend()方法:挂起,容易导致死锁;

    • 三种中断方式:

      • interrupt()方法:interrupt()方法中断一个线程,并不是强制关闭该线程,只是跟线程打声招呼,将线程的中断标志位置为true,线程是否中断,由线程本身决定;

      • inInterrupted()方法:判断当前线程是否处于中断状态;

      • static方法interrupted()方法:判断当前线程是否处于中断状态,并将中断标志位置为false;

    (注意:方法里如果抛出InterruptedException,线程的中断标志位会被置为false,如果确实需要中断线程,则需要在catch里面再次调用interrupt()方法。)

    Q3:

    sleep() 和 wait() 有什么区别?

    sleep()方法:

    • Thread类中的静态方法;

    • 当一个线程调用sleep()方法以后,不会释放同步资源锁,其他线程仍然会等待资源锁的释放。

    wait()方法:

    • Object类提供的一个普通方法;

    • 而且必须同步资源锁对象在同步代码块或者同步方法中调用。当调用wait()方法后,当前线程会立刻释放掉同步锁资源。其他线程就有机会获得同步资源锁从而继续往下执行。

    Q4:

    notify() 和 notifyAll() 方法有什么区别?

    尽量应该应用notifyAll()方法,如果用notify()方法的话,jvm会执行已经加入等待线程栈里面的第一个线程,给我们的一种感官就是随机的选择了一条线程,如果该线程达到条件就正好执行那一条,其实这是一个误区,这只是jvm会选择在线程栈里面的第一个线程来唤醒。因此用notify()方法的话,可能会造成信号丢失的情况。

    Q5:

    调用yield()、sleep()、wait()、notify()等方法对锁有何影响?

    1. 线程在执行yield()以后,持有的锁是不会释放的;

    2. sleep()方法被调用以后,持有的锁是不会释放的;

    3. 调用方法之前,必须要先持有锁。调用了wait()方法以后,锁就会被释放,当wait方法返回的时候,线程会重新持有锁;

    4. 调用方法之前,必须要先持有锁。调用notify()方法本身不会释放锁。

    Q6:

    创建多线程的方式有哪些?

    方式一:继承Thread类

    Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend Thread,并重写run()方法,,就可以启动新线程并执行自定义的run()方法。例如:继承Thread类实现多线程,并在适合的地方启动线程。

    public class MyThread extends Thread {
    ​  public void run() {
        System.out.println("MyThread.run()");
      }
    }
    
    MyThread myThread1 = new MyThread();
    MyThread myThread2 = new MyThread();
    myThread1.start();
    myThread2.start();

    方式二:实现Runnable接口的方式实现多线程,并且实例化Thread,传入自己的Thread实例,调用run()方法

    public class MyThread implements Runnable {
      public void run() {
        System.out.println("MyThread.run()");
      }
    }
    
    MyThread myThread = new MyThread();
    Thread thread = new Thread(myThread);
    thread.start();

    方式三:通过Callable 和 Future创建线程

    class T implements Callable<String> {
      @Override
      public String call() throws Exception {
        return null;
      }
    }

    明天,会介绍多线程一些深入的知识,长按二维码关注我吧~

    祝大家都能拿到心仪的offer!


    点关注、不迷路

    如果觉得文章不错,欢迎关注点赞收藏,你们的支持是我创作的动力,感谢大家。

    如果文章写的有问题,请不要吝啬,欢迎留言指出,我会及时核查修改。

    如果你还想更加深入的了解我,可以微信搜索「Java极客思维」进行关注。每天8:00准时推送技术文章,让你的上班路不在孤独,而且每月还有送书活动,助你提升硬实力!

  • 相关阅读:
    js- 类数组对象
    js- caller、 callee
    ES6 声明变量的6种方法
    Vue 之 element-ui upload组件的文件类型
    js中call、apply和bind的区别
    Vue 之 Vue.nextTick()
    DocumentFragment --更快捷操作DOM的途径
    Js 编程题汇总
    &#65279
    网站添加变量后变成空白
  • 原文地址:https://www.cnblogs.com/xgx120413/p/14088303.html
Copyright © 2020-2023  润新知