java多线程nullpointerexception_【技术干货】Java 面试宝典:Java 基础部分(5)

本文详细介绍了Java中final, finally, finalize的区别,运行时异常与一般异常的异同,error和exception的差异,以及Java异常处理机制的原理和应用。特别讨论了Java多线程相关知识点,包括线程创建方式、sleep()和wait()的区别,并分析了同步和异步编程的使用场景。" 102707400,7923968,VXLAN报文分片原理与配置,"['二层协议', '网络协议', 'VXLAN', '隧道技术']
摘要由CSDN通过智能技术生成

海牛学院的 | 第 634 

本文预计阅读 |   16  分钟 28a98774c5aa71bdf3872764694d2f93.png

28b82f600ee654518e6b594cf03a4793.gif

Java 基础部分

基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法。

40、final, finally, finalize 的区别是什么?

final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。内部类要访问局部变量,局部变量必须定义成 final 类型,例如,一段代码……finally 是异常处理语句结构的一部分,表示总是执行。

finalize 是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM 不保证此方法总被调用

41、运行时异常与一般异常有何异同?

异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java 编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。

42、error 和 exception 有什么区别?

error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。

43、讲一讲 Java 中的异常处理机制的简单原理和应用。

异常是指 java 程序运行时(非编译)所发生的非正常情况或错误,与现实生活中的事件很相似,现实生活中的事件可以包含事件发生的时间、地点、人物、情节等信息,可以用一个对象来表示,Java 使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一个对象来表示的,该对象中包含有异常的信息。

Java 对异常进行了分类,不同类型的异常分别用不同的 Java 类表示,所有异常的根类为java.lang.Throwable,Throwable 下面又派生了两个子类:Error 和 Exception,Error 表示应用程序本身无法克服和恢复的一种严重问题,程序只有死的份了,例如,说内存溢出和线程死锁等系统问题。

Exception 表示程序还能够克服和恢复的问题,其中又分为系统异常和普通异常,系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。

java 为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须 try..catch 处理或用 throws 声明继续抛给上层调用方法处理,所以普通异常也称为 checked 异常,而系统异常可以处理也可以不处理,所以,编译器不强制用 try..catch 处理或用 throws 声明,所以系统异常也称为 unchecked 异常。

提示:就按照三个级别去思考:虚拟机必须宕机的错误,程序可以死掉也可以不死掉的错误,程序不应该死掉的错误;

44、请写出你最常见到的 5 个 runtime exception。

这道题主要考你的代码量到底多大,如果你长期写代码的,应该经常都看到过一些系统方面的异常,你不一定真要回答出 5 个具体的系统异常,但你要能够说出什么是系统异常,以及几个系统异常就可以了,当然,这些异常完全用其英文名称来写是最好的,如果实在写不出,那就用中文吧,有总比没有强。

所谓系统异常,就是…..,它们都是 RuntimeException 的子类,在 jdk doc 中查 RuntimeException 类,就可以看到其所有的子类列表,也就是看到了所有的系统异常。常见的系统异常有:NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException。ArithmeticException - 算术运算中,被 0 除或模除. NoClassDefFoundException - JAVA 运行时系统找不到所引用的类..OutOfMemoryException - 内存不足,通常发生于创建对象之时。

45 、 JAVA 语言如何进行异常处理,关键字:throws、throw、try、catch、finally 分别代表什么意义?在 try 块中可以抛出异常吗?

略。

46、java 中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和 suspend()方法为何不推荐使用?

java5 以前,有如下两种:

第一种:new Thread(){}.start();这表示调用 Thread 子类对象的 run 方法,new Thread(){}表示一个Thread 的匿名子类的实例对象,子类加上 run 方法后的代码如下:

new Thread(){    public void run(){    }}.start();

第二种:new Thread(new Runnable(){}).start();这表示调用 Thread 对象接受的 Runnable 对象的 run方法,new Runnable(){}表示一个 Runnable 的匿名子类的实例对象,runnable 的子类加上 run 方法后的代码如下:

new Thread(new Runnable(){    public void run(){    }}).start();

从 java5 开始,还有如下一些线程池创建多线程的方式:

ExecutorService pool = Executors.newFixedThreadPool(3)for(int i=0;i<10;i++){    pool.execute(new Runable(){public void run(){}});}Executors.newCachedThreadPool().execute(new Runable(){public void run(){}});Executors.newSingleThreadExecutor().execute(new Runable(){public void run(){}});

有两种实现方法,分别使用 new Thread()和 new Thread(runnable)形式,第一种直接调用thread 的 run 方法,所以,我们往往使用 Thread 子类,即 new SubThread()。第二种调用 runnable 的 run 方法。

有两种实现方法,分别是继承 Thread 类与实现 Runnable 接口。

用 synchronized 关键字修饰同步方法。

反对使用 stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。

调用 suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。

所以不应该使用 suspend(),而应在自己的 Thread 类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用 wait()命其进入等待状态。若标志指出线程应当恢复,则用一个 notify()重新启动线程。

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

(网上的答案:sleep 是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时候会自动恢复。调用 sleep 不会释放对象锁。wait 是 Object 类的方法,对此对象调用 wait 方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出 notify 方法(或 notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。)

sleep 就是正在执行的线程主动让出 cpu,cpu 去执行其他线程,在 sleep 指定的时间过后,cpu 才会回到这个线程上继续往下执行,如果当前线程进入了同步锁,sleep 方法并不会释放锁,即使当前线程使用 sleep 方法让出了 cpu,但其他被同步锁挡住了的线程也无法得到执行。

wait 是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了 notify 方法(notify 并不释放锁,只是告诉调用过 wait 方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放。

如果 notify 方法后面的代码还有很多,需要这些代码执行完后才会释放锁,可以在 notfiy 方法后增加一个等待和一些代码,看看效果),调用 wait方法的线程就会解除 wait 状态和程序可以再次得到锁后继续向下运行。对于 wait 的讲解一定要配合例子代码来说明,才显得自己真明白。

package com.huawei.interview;public class MultiThread {    /**    * @param args    */    public static void main(String[] args) {        // TODO Auto-generated method stub        new Thread(new Thread1()).start();        try {            Thread.sleep(10);        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        new Thread(new Thread2()).start();    }        private static class Thread1 implements Runnable    {            @Override        public void run() {            // TODO Auto-generated method stub//由于这里的Thread1和下面的Thread2内部run方法要用同一对象作为监视器,我们这里不能用this,因为在Thread2里面的this和这个Thread1的this不是同一个对象。我们用MultiThread.class这个字节码对象,当前虚拟机里引用这个变量时,指向的都是同一个对象。            synchronized (MultiThread.class) {                            System.out.println("enter thread1...");                                System.out.println("thread1 is waiting");                try {                //释放锁有两种方式,第一种方式是程序自然离开监视器的范围,也就是离开了synchronized关键字管辖的代码范围,另一种方式就是在synchronized关键字管辖的代码内部调用监视器对象的wait方法。这里,使用wait方法释放锁。                    MultiThread.class.wait();                } catch (InterruptedException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }                                System.out.println("thread1 is going on...");                System.out.println("thread1 is being over!");            }         }    }        private static class Thread2 implements Runnable    {            @Override        public void run() {            // TODO Auto-generated method stub            synchronized (MultiThread.class) {                            System.out.println("enter thread2...");                                System.out.println("thread2 notify other thread can                 release wait status..");//由于notify方法并不释放锁, 即使thread2调用下面的sleep方法休息了10毫秒,但thread1仍然不会执行,因为thread2没有释放锁,所以Thread1无法得不到锁。                               MultiThread.class.notify();                                System.out.println("thread2 is sleeping ten millisecond...");                try {                    Thread.sleep(10);                } catch (InterruptedException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }                                System.out.println("thread2 is going on...");                System.out.println("thread2 is being over!");                                }         }    } }

48、同步和异步有何异同,在什么情况下分别使用他们?举例说明。

如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。

49. 下面两个方法同步吗?

class Test {         synchronized static void sayHello3()         {                  }                  synchronized void getX(){} }

答:略。

50、多线程有几种实现方法?同步有几种实现方法?

多线程有两种实现方法,分别是继承 Thread 类与实现 Runnable 接口。

同步的实现方面有两种,分别是 synchronized,wait 与 notify。

wait():使一个线程处于等待状态,并且释放所持有的对象的 lock。

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException 异常。

notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由 JVM 确定唤醒哪个线程,而且不是按优先级。

Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

9674a8ffc015e703b7b5ff902941f22a.png

总结 以上就是今天的内容了,如果对你有所帮助,希望你能够关注、点赞、转发一键三连支持一下。 需要完整学习线路和配套课堂笔记,请后台回复【学习线路、笔记、思维导图】,更多技术干货请在后台回复【技术论坛】

备注 “ 进群 ” (广告勿扰)

【海牛大数据交流群】

ab69cbc8f3f2b617c9d4be75ea9c0403.png e83a6ee49777c3048b045365f4e317bf.png bc8643e2bc2ce5a80ecf8cc473c60392.png 0d3c00419d7170ac4d8d5ddfb50f6409.png 9b763003f148b99fa4c8596cfa87c2af.png 3ad79f4f5a076987d7381d2c5cda5bb8.png  要点赞,要在看 ↓↓↓
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值