精华内容
下载资源
问答
  • 我们知道在Java里线程通过java.lang.Thread类来实现。一般我们创建无返回值线程会用下面两个方法: 继承Thread类,重写run()方法; 实现Runnable接口,重写run()方法; 线程启动会通过调用start方法来启动...

    线程的创建

    我们知道在Java里线程是通过java.lang.Thread类来实现的。一般我们创建无返回值的线程会用下面两个方法:

    1. 继承Thread类,重写run()方法;
    2. 实现Runnable接口,重写run()方法;

    线程启动会通过调用start方法来启动线程而不能直接调用run方法。

    这里就会引出两个经典的面试题:

    1. 为什么线程启动是调用start方法来启动线程而不能直接调用run方法?
    2. 如果多次调用start方法会发生什么?

    其实答案就是源码里,在这之前我们要了解线程的状态有哪些。

    线程的状态

    线程从创建到死亡是会经历多个状态的流转的。它们分别是:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED

    Java-Thread-Status

    // Thread类的内部的枚举类定义了线程的状态
    public enum State {
        NEW,
        RUNNABLE,
        BLOCKED,
        WAITING,
        TIMED_WAITING,
        TERMINATED;
    }
    

    start() 方法 & run()方法

    为什么线程启动是调用start方法来启动线程而不能直接调用run方法?

    从上图中,我们就可以看到,在New了一个线程后,首先进入初始态,然后调用start()方法来到就绪态,这里并不会立即执行线程里的任务,而是会等待系统资源分配,当分配到时间片后就可以开始运行了。 start()方法是一个native方法,它将启动一个新线程,并执行run()方法,这是真正的多线程工作。 而直接执行 run() 方法,会把 run 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。这就是为什么调用 start() 方法时会执行 run() 方法,为什么不能直接调用 run() 方法的原因了。

    Example:

    public class ThreadDemo    
    		public static void main(String[] args) {
            Thread t1 = new Thread(new Task1());
            Thread t2 = new Thread(new Task2());
    
      			// 测试1
            t1.start();
            t2.start();
    
     				// 测试2
            t1.run();
            t2.run();
    
        }
    }
    
    class Task1 implements Runnable {
    
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println("Task1: " + i);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    class Task2 implements Runnable {
    
        @Override
        public void run() {
            for (int i = 10; i > 0; i--) {
                System.out.println("Task2: " + i);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    
    // 测试1输出
    Task1: 0
    Task2: 10
    Task1: 1
    Task2: 9
    Task1: 2
    Task2: 8
    Task1: 3
    Task2: 7
    Task1: 4
    Task2: 6
    Task1: 5
    Task2: 5
    Task1: 6
    Task2: 4
    Task1: 7
    Task2: 3
    Task1: 8
    Task2: 2
    Task1: 9
    Task2: 1
    我们可以看到Task1 和 Task2是交替打印的,是多线程在运行。
    // 测试2输出
    Task1: 0
    Task1: 1
    Task1: 2
    Task1: 3
    Task1: 4
    Task1: 5
    Task1: 6
    Task1: 7
    Task1: 8
    Task1: 9
    Task2: 10
    Task2: 9
    Task2: 8
    Task2: 7
    Task2: 6
    Task2: 5
    Task2: 4
    Task2: 3
    Task2: 2
    Task2: 1
    这个的输出是串行的,Task1 执行完才执行 Task2,所以不是多线程,是普通方法。
    

    如果多次调用start方法会发生什么?

    首先我们先测试一下。

    Example:

    public class ThreadDemo    
    		public static void main(String[] args) {
            Thread t1 = new Thread(new Task1());
            Thread t2 = new Thread(new Task2());
    
      			// 测试3
            t1.start();
            t1.start();
        }
    }
    
    // 测试3输出
    Task1: 0
    Task...
    Exception in thread "main" java.lang.IllegalThreadStateException
    	at java.lang.Thread.start(Thread.java:708)
    Task...
    

    只有第一次成功执行,后面就抛出了异常java.lang.IllegalThreadStateException,让我们来从下面的源码里看看吧,在start方法进来后就会判断线程的状态,如果不是初始态状态就会抛出异常,所以第二次执行就会报错,因为线程的状态已经发生改变。

    源码

    start()方法源码:

        public synchronized void start() {  
            // 如果线程不是"NEW状态",则抛出异常!  
            if (threadStatus != 0)  
                throw new IllegalThreadStateException();  
            // 将线程添加到ThreadGroup中  
            group.add(this);  
            boolean started = false;  
            try {  
                // 通过start0()启动线程,新线程会调用run()方法  
                start0();  
                // 设置started标记=true  
                started = true;  
            } finally {  
                try {  
                    if (!started) {  
                        group.threadStartFailed(this);  
                    }  
                } catch (Throwable ignore) {  
                }  
            }  
        }  
    

    run方法源码:

    public void run() {  
        if (target != null) {  
            target.run();  
        }  
    } 
    

    总结

    start()方法是用来启动线程,真正实现了多线程运行。

    run()方法是一个普通方法。

    调用start()方法后会先判断线程的状态是否为NEW,所以线程只能启动一次。


    求关注、分享、在看!!! 你的支持是我创作最大的动力。

    展开全文
  • Java 笔试题 可多选 下面哪些是 Thread 类的方法 ABD A start) B run) C exit) D getPriority) 下面关于类的说法正确的是 A A 继承自 Throwable Serialable 该类实现了 Throwable 接口 该类是一个公共类 3....
  • 1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD 解析:看Java API docs吧:http://docs.oracle.com/javase/7/docs/api/,exit()是System类的方法,如System.exit(0)。 2. ...

    在这里插入图片描述

    1. 下面哪些是Thread类的方法()

    A start() B run() C exit() D getPriority()

    答案:ABD

    解析:看Java API docs吧:http://docs.oracle.com/javase/7/docs/api/,exit()是System类的方法,如System.exit(0)。

    2. 下面关于java.lang.Exception类的说法正确的是()

    A 继承自Throwable B Serialable CD 不记得,反正不正确

    答案:A

    解析:Java异常的基类为java.lang.Throwable,java.lang.Error和java.lang.Exception继承 Throwable,RuntimeException和其它的Exception等继承Exception,具体的RuntimeException继承RuntimeException。
    扩展:错误和异常的区别(Error vs Exception)

    1. java.lang.Error: Throwable的子类,用于标记严重错误。合理的应用程序不应该去try/catch这种错误。绝大多数的错误都是非正常的,就根本不该出现的。
      java.lang.Exception: Throwable的子类,用于指示一种合理的程序想去catch的条件。即它仅仅是一种程序运行条件,而非严重错误,并且鼓励用户程序去catch它。

    2. Error和RuntimeException 及其子类都是未检查的异常(unchecked exceptions),而所有其他的Exception类都是检查了的异常(checked exceptions).
      checked exceptions: 通常是从一个可以恢复的程序中抛出来的,并且最好能够从这种异常中使用程序恢复。比如FileNotFoundException, ParseException等。检查了的异常发生在编译阶段,必须要使用try…catch(或者throws)否则编译不通过。
      unchecked exceptions: 通常是如果一切正常的话本不该发生的异常,但是的确发生了。发生在运行期,具有不确定性,主要是由于程序的逻辑问题所引起的。比如ArrayIndexOutOfBoundException, ClassCastException等。从语言本身的角度讲,程序不该去catch这类异常,虽然能够从诸如RuntimeException这样的异常中catch并恢复,但是并不鼓励终端程序员这么做,因为完全没要必要。因为这类错误本身就是bug,应该被修复,出现此类错误时程序就应该立即停止执行。 因此,面对Errors和unchecked exceptions应该让程序自动终止执行,程序员不该做诸如try/catch这样的事情,而是应该查明原因,修改代码逻辑。

    RuntimeException:RuntimeException体系包括错误的类型转换、数组越界访问和试图访问空指针等等。

    处理RuntimeException的原则是:如果出现 RuntimeException,那么一定是程序员的错误。例如,可以通过检查数组下标和数组边界来避免数组越界访问异常。其他(IOException等等)checked异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。

    3. 下面程序的运行结果是()

    String str1 = “hello”;
    String str2 = “he” + new String(“llo”);
    System.err.println(str1 == str2);
    答案:false

    解析:因为str2中的llo是新申请的内存块,而==判断的是对象的地址而非值,所以不一样。如果是String str2 = str1,那么就是true了。

    4. 下列说法正确的有()

    A. class中的constructor不可省略

    B. constructor必须与class同名,但方法不能与class同名

    C. constructor在一个对象被new时执行

    D.一个class只能定义一个constructor

    答案:C

    解析:这里可能会有误区,其实普通的类方法是可以和类名同名的,和构造方法唯一的区分就是,构造方法没有返回值。

    5. 具体选项不记得,但用到的知识如下:

    String []a = new String[10];

    则:a[0]~a[9] = null

    a.length = 10

    如果是int []a = new int[10];

    则:a[0]~a[9] = 0

    a.length = 10

    6. 下面程序的运行结果:()

    public static void main(String args[]) {
     
        Thread t = new Thread() {
     
            public void run() {
                pong();
            }
        };
     
        t.run();
        System.out.print("ping");
     
    }
     
    static void pong() {
     
        System.out.print("pong");
     
    }
    

    A pingpong B pongping C pingpong和pongping都有可能 D 都不输出

    答案:B

    解析:这里考的是Thread类中start()和run()方法的区别了。start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程,进而调用run()方法来执行任务,而单独的调用run()就跟调用普通方法是一样的,已经失去线程的特性了。因此在启动一个线程的时候一定要使用start()而不是run()。

    7. 下列属于关系型数据库的是()

    A. Oracle B MySql C IMS D MongoDB

    答案:AB

    解答:IMS(Information Management System )数据库是IBM公司开发的两种数据库类型之一;

    一种是关系数据库,典型代表产品:DB2;

    另一种则是层次数据库,代表产品:IMS层次数据库。

    非关系型数据库有MongoDB、memcachedb、Redis等。

    8. GC线程是否为守护线程?()

    答案:是

    解析:线程分为守护线程和非守护线程(即用户线程)。

    只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。
    守护线程最典型的应用就是 GC (垃圾回收器)

    9. volatile关键字是否能保证线程安全?()

    答案:不能

    解析:volatile关键字用在多线程同步中,可保证读取的可见性,JVM只是保证从主内存加载到线程工作内存的值是最新的读取值,而非cache中。但多个线程对

    volatile的写操作,无法保证线程安全。例如假如线程1,线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值,在线程1堆count进行修改之后,会write到主内存中,主内存中的count变量就会变为6;线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6;导致两个线程及时用volatile关键字修改之后,还是会存在并发的情况。

    10. 下列说法正确的是()

    A LinkedList继承自List

    B AbstractSet继承自Set

    C HashSet继承自AbstractSet

    D WeakMap继承自HashMap

    答案:AC

    解析:下面是一张下载的Java中的集合类型的继承关系图,一目了然。

    11. 存在使i + 1 < i的数吗()

    答案:存在

    解析:如果i为int型,那么当i为int能表示的最大整数时,i+1就溢出变成负数了,此时不就<i了吗。

    扩展:存在使i > j || i <= j不成立的数吗()

    答案:存在

    解析:比如Double.NaN或Float.NaN,感谢@BuilderQiu网友指出。

    12. 0.6332的数据类型是()

    A float B double C Float D Double

    答案:B

    解析:默认为double型,如果为float型需要加上f显示说明,即0.6332f

    13. 下面哪个流类属于面向字符的输入流( )

    A BufferedWriter B FileInputStream C ObjectInputStream D InputStreamReader

    答案:D

    解析:Java的IO操作中有面向字节(Byte)和面向字符(Character)两种方式。
    面向字节的操作为以8位为单位对二进制的数据进行操作,对数据不进行转换,这些类都是InputStream和OutputStream的子类。
    面向字符的操作为以字符为单位对数据进行操作,在读的时候将二进制数据转为字符,在写的时候将字符转为二进制数据,这些类都是Reader和Writer的子类。

    总结:以InputStream(输入)/OutputStream(输出)为后缀的是字节流;

          以Reader(输入)/Writer(输出)为后缀的是字符流。
    

    扩展:Java流类图结构,一目了然,解决大部分选择题:
    在这里插入图片描述
    14. Java接口的修饰符可以为()

    A private B protected C final D abstract

    答案:CD

    解析:接口很重要,为了说明情况,这里稍微啰嗦点:

    (1)接口用于描述系统对外提供的所有服务,因此接口中的成员常量和方法都必须是公开(public)类型的,确保外部使用者能访问它们;

    (2)接口仅仅描述系统能做什么,但不指明如何去做,所以接口中的方法都是抽象(abstract)方法;

    (3)接口不涉及和任何具体实例相关的细节,因此接口没有构造方法,不能被实例化,没有实例变量,只有静态(static)变量;

    (4)接口的中的变量是所有实现类共有的,既然共有,肯定是不变的东西,因为变化的东西也不能够算共有。所以变量是不可变(final)类型,也就是常量了。

    (5) 接口中不可以定义变量?如果接口可以定义变量,但是接口中的方法又都是抽象的,在接口中无法通过行为来修改属性。有的人会说了,没有关系,可以通过 实现接口的对象的行为来修改接口中的属性。这当然没有问题,但是考虑这样的情况。如果接口 A 中有一个public 访问权限的静态变量 a。按照 Java 的语义,我们可以不通过实现接口的对象来访问变量 a,通过 A.a = xxx; 就可以改变接口中的变量 a 的值了。正如抽象类中是可以这样做的,那么实现接口 A 的所有对象也都会自动拥有这一改变后的 a 的值了,也就是说一个地方改变了 a,所有这些对象中 a 的值也都跟着变了。这和抽象类有什么区别呢,怎么体现接口更高的抽象级别呢,怎么体现接口提供的统一的协议呢,那还要接口这种抽象来做什么呢?所以接口中 不能出现变量,如果有变量,就和接口提供的统一的抽象这种思想是抵触的。所以接口中的属性必然是常量,只能读不能改,这样才能为实现接口的对象提供一个统 一的属性。

    通俗的讲,你认为是要变化的东西,就放在你自己的实现中,不能放在接口中去,接口只是对一类事物的属性和行为更高层次的抽象。对修改关闭,对扩展(不同的实现 implements)开放,接口是对开闭原则的一种体现。

    所以:

    接口的方法默认是public abstract;

    接口中不可以定义变量即只能定义常量(加上final修饰就会变成常量)。所以接口的属性默认是public static final 常量,且必须赋初值。

    注意:final和abstract不能同时出现。

    15. 不通过构造函数也能创建对象吗()

    A 是 B 否

    答案:A

    解析:Java创建对象的几种方式(重要):

    (1) 用new语句创建对象,这是最常见的创建对象的方法。
    (2) 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
    (3) 调用对象的clone()方法。
    (4) 运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。

    (1)和(2)都会明确的显式的调用构造函数 ;(3)是在内存上对已有对象的影印,所以不会调用构造函数 ;(4)是从文件中还原类的对象,也不会调用构造函数。

    16. ArrayList list = new ArrayList(20);中的list扩充几次()

    A 0 B 1 C 2 D 3

    答案:A

    解析:这里有点迷惑人,大家都知道默认ArrayList的长度是10个,所以如果你要往list里添加20个元素肯定要扩充一次(扩充为原来的1.5倍),但是这里显示指明了需要多少空间,所以就一次性为你分配这么多空间,也就是不需要扩充了。

    17. 下面哪些是对称加密算法()

    A DES B AES C DSA D RSA

    答案:AB

    解析:常用的对称加密算法有:DES、3DES、RC2、RC4、AES

    常用的非对称加密算法有:RSA、DSA、ECC

    使用单向散列函数的加密算法:MD5、SHA

    18.新建一个流对象,下面哪个选项的代码是错误的?()

    A)new BufferedWriter(new FileWriter(“a.txt”));

    B)new BufferedReader(new FileInputStream(“a.dat”));

    C)new GZIPOutputStream(new FileOutputStream(“a.zip”));

    D)new ObjectInputStream(new FileInputStream(“a.dat”));

    答案:B

    解析:请记得13题的那个图吗?Reader只能用FileReader进行实例化。

    19. 下面程序能正常运行吗()

    public class NULL {

    public static void haha(){
        System.out.println("haha");
    }
    public static void main(String[] args) {
        ((NULL)null).haha();
    }
    

    }
    答案:能正常运行

    解析:输出为haha,因为null值可以强制转换为任何java类类型,(String)null也是合法的。但null强制转换后是无效对象,其返回值还是为null,而static方法的调用是和类名绑定的,不借助对象进行访问所以能正确输出。反过来,没有static修饰就只能用对象进行访问,使用null调用对象肯定会报空指针错了。这里和C++很类似。这里感谢@Florian网友解答。

    class HelloA {
     
        public HelloA() {
            System.out.println("HelloA");
        }
         
        { System.out.println("I'm A class"); }
         
        static { System.out.println("static A"); }
     
    }
     
    public class HelloB extends HelloA {
        public HelloB() {
            System.out.println("HelloB");
        }
         
        { System.out.println("I'm B class"); }
         
        static { System.out.println("static B"); }
         
        public static void main(String[] args) { 
         new HelloB(); 
       }
     
    }
    

    答案:

    static A
    static B
    I’m A class
    HelloA
    I’m B class
    HelloB

    解析:说实话我觉得这题很好,考查静态语句块、构造语句块(就是只有大括号的那块)以及构造函数的执行顺序。

    对象的初始化顺序:(1)类加载之后,按从上到下(从父类到子类)执行被static修饰的语句;(2)当static语句执行完之后,再执行main方法;(3)如果有语句new了自身的对象,将从上到下执行构造代码块、构造器(两者可以说绑定在一起)。

    下面稍微修改下上面的代码,以便更清晰的说明情况:

    class HelloA {
     
        public HelloA() {
            System.out.println("HelloA");
        }
         
        { System.out.println("I'm A class"); }
         
        static { System.out.println("static A"); }
     
    }
     
    public class HelloB extends HelloA {
        public HelloB() {
            System.out.println("HelloB");
        }
         
        { System.out.println("I'm B class"); }
         
        static { System.out.println("static B"); }
         
        public static void main(String[] args) {
     
            System.out.println("-------main start-------");
            new HelloB();
            new HelloB();
            System.out.println("-------main end-------");
        }
    }
    

    此时输出结果为:

    static A
    static B
    -------main start-------
    I’m A class
    HelloA
    I’m B class
    HelloB
    I’m A class
    HelloA
    I’m B class
    HelloB
    -------main end-------

    20. getCustomerInfo()方法如下,try中可以捕获三种类型的异常,如果在该方法运行中产生了一个IOException,将会输出什么结果()

    public void getCustomerInfo() {
     
        try {
     
            // do something that may cause an Exception
     
        } catch (java.io.FileNotFoundException ex) {
     
            System.out.print("FileNotFoundException!");
     
        } catch (java.io.IOException ex) {
     
            System.out.print("IOException!");
     
        } catch (java.lang.Exception ex) {
     
            System.out.print("Exception!");
     
        }
     
    }
    

    A IOException!

    BIOException!Exception!

    CFileNotFoundException!IOException!

    DFileNotFoundException!IOException!Exception!

    答案:A

    解析:考察多个catch语句块的执行顺序。当用多个catch语句时,catch语句块在次序上有先后之分。从最前面的catch语句块依次先后进行异常类型匹配,这样如果父异常在子异常类之前,那么首先匹配的将是父异常类,子异常类将不会获得匹配的机会,也即子异常类型所在的catch语句块将是不可到达的语句。所以,一般将父类异常类即Exception老大放在catch语句块的最后一个。

    21. 下面代码的运行结果为:()

    import java.io.*;
    import java.util.*;
     
    public class foo{
     
        public static void main (String[] args){
     
            String s;
     
            System.out.println("s=" + s);
     
        }
    }
    

    A 代码得到编译,并输出“s=”

    B 代码得到编译,并输出“s=null”

    C 由于String s没有初始化,代码不能编译通过

    D 代码得到编译,但捕获到 NullPointException异常
    答案:C

    解析:开始以为会输出null什么的,运行后才发现Java中所有定义的基本类型或对象都必须初始化才能输出值。

    1. System.out.println(“5” + 2);的输出结果应该是()。

    A 52 B7 C2 D5

    答案:A

    解析:没啥好说的,Java会自动将2转换为字符串。

    22. 指出下列程序运行的结果 ()

    public class Example {
     
        String str = new String("good");
     
        char[] ch = { 'a', 'b', 'c' };
     
        public static void main(String args[]) {
     
            Example ex = new Example();
     
            ex.change(ex.str, ex.ch);
     
            System.out.print(ex.str + " and ");
     
            System.out.print(ex.ch);
     
        }
     
        public void change(String str, char ch[]) {
     
            str = "test ok";
     
            ch[0] = 'g';
     
        }
    }
    

    A、 good and abc

    B、 good and gbc

    C、 test ok and abc

    D、 test ok and gbc
    答案:B

    文末

    都是一些非常非常基础的题,是我最近参加各大IT公司笔试后靠记忆记下来的,经过整理献给与我一样参加各大IT校园招聘的同学们,纯考Java基础功底,老手们就不用进来了,免得笑话我们这些未出校门的孩纸们,但是IT公司就喜欢考这些基础的东西。花了不少时间整理,在整理过程中也学到了很多东西,请大家认真对待每一题~~~
    到此这篇关于JAVA题的分享就到这里了,如果看不过瘾本人另外整理收藏了20年多家公司面试知识点整理 ,以及各种Java核心知识点免费分享给大家,想要资料的话请点击这里暗号 qf 。
    在这里插入图片描述

    展开全文
  • 1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD 解析:看Java API docs吧:http://docs.oracle.com/javase/7/docs/api/,exit()是System类的方法,如System.exit(0)。 ...

    在这里插入图片描述

    1. 下面哪些是Thread类的方法()

    A start() B run() C exit() D getPriority()

    答案:ABD

    解析:看Java API docs吧:http://docs.oracle.com/javase/7/docs/api/,exit()是System类的方法,如System.exit(0)。

    2. 下面关于java.lang.Exception类的说法正确的是()

    A 继承自Throwable B Serialable CD 不记得,反正不正确

    答案:A

    解析:Java异常的基类为java.lang.Throwable,java.lang.Error和java.lang.Exception继承 Throwable,RuntimeException和其它的Exception等继承Exception,具体的RuntimeException继承RuntimeException。
    扩展:错误和异常的区别(Error vs Exception)

    1. java.lang.Error: Throwable的子类,用于标记严重错误。合理的应用程序不应该去try/catch这种错误。绝大多数的错误都是非正常的,就根本不该出现的。
      java.lang.Exception: Throwable的子类,用于指示一种合理的程序想去catch的条件。即它仅仅是一种程序运行条件,而非严重错误,并且鼓励用户程序去catch它。

    2. Error和RuntimeException 及其子类都是未检查的异常(unchecked exceptions),而所有其他的Exception类都是检查了的异常(checked exceptions).
      checked exceptions: 通常是从一个可以恢复的程序中抛出来的,并且最好能够从这种异常中使用程序恢复。比如FileNotFoundException, ParseException等。检查了的异常发生在编译阶段,必须要使用try…catch(或者throws)否则编译不通过。
      unchecked exceptions: 通常是如果一切正常的话本不该发生的异常,但是的确发生了。发生在运行期,具有不确定性,主要是由于程序的逻辑问题所引起的。比如ArrayIndexOutOfBoundException, ClassCastException等。从语言本身的角度讲,程序不该去catch这类异常,虽然能够从诸如RuntimeException这样的异常中catch并恢复,但是并不鼓励终端程序员这么做,因为完全没要必要。因为这类错误本身就是bug,应该被修复,出现此类错误时程序就应该立即停止执行。 因此,面对Errors和unchecked exceptions应该让程序自动终止执行,程序员不该做诸如try/catch这样的事情,而是应该查明原因,修改代码逻辑。

    RuntimeException:RuntimeException体系包括错误的类型转换、数组越界访问和试图访问空指针等等。

    处理RuntimeException的原则是:如果出现 RuntimeException,那么一定是程序员的错误。例如,可以通过检查数组下标和数组边界来避免数组越界访问异常。其他(IOException等等)checked异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。

    3. 下面程序的运行结果是()

    String str1 = “hello”;
    String str2 = “he” + new String(“llo”);
    System.err.println(str1 == str2);
    答案:false

    解析:因为str2中的llo是新申请的内存块,而==判断的是对象的地址而非值,所以不一样。如果是String str2 = str1,那么就是true了。

    4. 下列说法正确的有()

    A. class中的constructor不可省略

    B. constructor必须与class同名,但方法不能与class同名

    C. constructor在一个对象被new时执行

    D.一个class只能定义一个constructor

    答案:C

    解析:这里可能会有误区,其实普通的类方法是可以和类名同名的,和构造方法唯一的区分就是,构造方法没有返回值。

    5. 具体选项不记得,但用到的知识如下:

    String []a = new String[10];

    则:a[0]~a[9] = null

    a.length = 10

    如果是int []a = new int[10];

    则:a[0]~a[9] = 0

    a.length = 10

    6. 下面程序的运行结果:()

    public static void main(String args[]) {
     
        Thread t = new Thread() {
     
            public void run() {
                pong();
            }
        };
     
        t.run();
        System.out.print("ping");
     
    }
     
    static void pong() {
     
        System.out.print("pong");
     
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    A pingpong B pongping C pingpong和pongping都有可能 D 都不输出

    答案:B

    解析:这里考的是Thread类中start()和run()方法的区别了。start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程,进而调用run()方法来执行任务,而单独的调用run()就跟调用普通方法是一样的,已经失去线程的特性了。因此在启动一个线程的时候一定要使用start()而不是run()。

    7. 下列属于关系型数据库的是()

    A. Oracle B MySql C IMS D MongoDB

    答案:AB

    解答:IMS(Information Management System )数据库是IBM公司开发的两种数据库类型之一;

    一种是关系数据库,典型代表产品:DB2;

    另一种则是层次数据库,代表产品:IMS层次数据库。

    非关系型数据库有MongoDB、memcachedb、Redis等。

    8. GC线程是否为守护线程?()

    答案:是

    解析:线程分为守护线程和非守护线程(即用户线程)。

    只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。
    守护线程最典型的应用就是 GC (垃圾回收器)

    9. volatile关键字是否能保证线程安全?()

    答案:不能

    解析:volatile关键字用在多线程同步中,可保证读取的可见性,JVM只是保证从主内存加载到线程工作内存的值是最新的读取值,而非cache中。但多个线程对

    volatile的写操作,无法保证线程安全。例如假如线程1,线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值,在线程1堆count进行修改之后,会write到主内存中,主内存中的count变量就会变为6;线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6;导致两个线程及时用volatile关键字修改之后,还是会存在并发的情况。

    10. 下列说法正确的是()

    A LinkedList继承自List

    B AbstractSet继承自Set

    C HashSet继承自AbstractSet

    D WeakMap继承自HashMap

    答案:AC

    解析:下面是一张下载的Java中的集合类型的继承关系图,一目了然。

    11. 存在使i + 1 < i的数吗()

    答案:存在

    解析:如果i为int型,那么当i为int能表示的最大整数时,i+1就溢出变成负数了,此时不就<i了吗。

    扩展:存在使i > j || i <= j不成立的数吗()

    答案:存在

    解析:比如Double.NaN或Float.NaN,感谢@BuilderQiu网友指出。

    12. 0.6332的数据类型是()

    A float B double C Float D Double

    答案:B

    解析:默认为double型,如果为float型需要加上f显示说明,即0.6332f

    13. 下面哪个流类属于面向字符的输入流( )

    A BufferedWriter B FileInputStream C ObjectInputStream D InputStreamReader

    答案:D

    解析:Java的IO操作中有面向字节(Byte)和面向字符(Character)两种方式。
    面向字节的操作为以8位为单位对二进制的数据进行操作,对数据不进行转换,这些类都是InputStream和OutputStream的子类。
    面向字符的操作为以字符为单位对数据进行操作,在读的时候将二进制数据转为字符,在写的时候将字符转为二进制数据,这些类都是Reader和Writer的子类。

    总结:以InputStream(输入)/OutputStream(输出)为后缀的是字节流;

          以Reader(输入)/Writer(输出)为后缀的是字符流。
    
    • 1

    扩展:Java流类图结构,一目了然,解决大部分选择题:
    在这里插入图片描述
    14. Java接口的修饰符可以为()

    A private B protected C final D abstract

    答案:CD

    解析:接口很重要,为了说明情况,这里稍微啰嗦点:

    (1)接口用于描述系统对外提供的所有服务,因此接口中的成员常量和方法都必须是公开(public)类型的,确保外部使用者能访问它们;

    (2)接口仅仅描述系统能做什么,但不指明如何去做,所以接口中的方法都是抽象(abstract)方法;

    (3)接口不涉及和任何具体实例相关的细节,因此接口没有构造方法,不能被实例化,没有实例变量,只有静态(static)变量;

    (4)接口的中的变量是所有实现类共有的,既然共有,肯定是不变的东西,因为变化的东西也不能够算共有。所以变量是不可变(final)类型,也就是常量了。

    (5) 接口中不可以定义变量?如果接口可以定义变量,但是接口中的方法又都是抽象的,在接口中无法通过行为来修改属性。有的人会说了,没有关系,可以通过 实现接口的对象的行为来修改接口中的属性。这当然没有问题,但是考虑这样的情况。如果接口 A 中有一个public 访问权限的静态变量 a。按照 Java 的语义,我们可以不通过实现接口的对象来访问变量 a,通过 A.a = xxx; 就可以改变接口中的变量 a 的值了。正如抽象类中是可以这样做的,那么实现接口 A 的所有对象也都会自动拥有这一改变后的 a 的值了,也就是说一个地方改变了 a,所有这些对象中 a 的值也都跟着变了。这和抽象类有什么区别呢,怎么体现接口更高的抽象级别呢,怎么体现接口提供的统一的协议呢,那还要接口这种抽象来做什么呢?所以接口中 不能出现变量,如果有变量,就和接口提供的统一的抽象这种思想是抵触的。所以接口中的属性必然是常量,只能读不能改,这样才能为实现接口的对象提供一个统 一的属性。

    通俗的讲,你认为是要变化的东西,就放在你自己的实现中,不能放在接口中去,接口只是对一类事物的属性和行为更高层次的抽象。对修改关闭,对扩展(不同的实现 implements)开放,接口是对开闭原则的一种体现。

    所以:

    接口的方法默认是public abstract;

    接口中不可以定义变量即只能定义常量(加上final修饰就会变成常量)。所以接口的属性默认是public static final 常量,且必须赋初值。

    注意:final和abstract不能同时出现。

    15. 不通过构造函数也能创建对象吗()

    A 是 B 否

    答案:A

    解析:Java创建对象的几种方式(重要):

    (1) 用new语句创建对象,这是最常见的创建对象的方法。
    (2) 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
    (3) 调用对象的clone()方法。
    (4) 运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。

    (1)和(2)都会明确的显式的调用构造函数 ;(3)是在内存上对已有对象的影印,所以不会调用构造函数 ;(4)是从文件中还原类的对象,也不会调用构造函数。

    16. ArrayList list = new ArrayList(20);中的list扩充几次()

    A 0 B 1 C 2 D 3

    答案:A

    解析:这里有点迷惑人,大家都知道默认ArrayList的长度是10个,所以如果你要往list里添加20个元素肯定要扩充一次(扩充为原来的1.5倍),但是这里显示指明了需要多少空间,所以就一次性为你分配这么多空间,也就是不需要扩充了。

    17. 下面哪些是对称加密算法()

    A DES B AES C DSA D RSA

    答案:AB

    解析:常用的对称加密算法有:DES、3DES、RC2、RC4、AES

    常用的非对称加密算法有:RSA、DSA、ECC

    使用单向散列函数的加密算法:MD5、SHA

    18.新建一个流对象,下面哪个选项的代码是错误的?()

    A)new BufferedWriter(new FileWriter(“a.txt”));

    B)new BufferedReader(new FileInputStream(“a.dat”));

    C)new GZIPOutputStream(new FileOutputStream(“a.zip”));

    D)new ObjectInputStream(new FileInputStream(“a.dat”));

    答案:B

    解析:请记得13题的那个图吗?Reader只能用FileReader进行实例化。

    19. 下面程序能正常运行吗()

    public class NULL {

    public static void haha(){
        System.out.println("haha");
    }
    public static void main(String[] args) {
        ((NULL)null).haha();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    }
    答案:能正常运行

    解析:输出为haha,因为null值可以强制转换为任何java类类型,(String)null也是合法的。但null强制转换后是无效对象,其返回值还是为null,而static方法的调用是和类名绑定的,不借助对象进行访问所以能正确输出。反过来,没有static修饰就只能用对象进行访问,使用null调用对象肯定会报空指针错了。这里和C++很类似。这里感谢@Florian网友解答。

    class HelloA {
     
        public HelloA() {
            System.out.println("HelloA");
        }
         
        { System.out.println("I'm A class"); }
         
        static { System.out.println("static A"); }
     
    }
     
    public class HelloB extends HelloA {
        public HelloB() {
            System.out.println("HelloB");
        }
         
        { System.out.println("I'm B class"); }
         
        static { System.out.println("static B"); }
         
        public static void main(String[] args) { 
         new HelloB(); 
       }
     
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    答案:

    static A
    static B
    I’m A class
    HelloA
    I’m B class
    HelloB

    解析:说实话我觉得这题很好,考查静态语句块、构造语句块(就是只有大括号的那块)以及构造函数的执行顺序。

    对象的初始化顺序:(1)类加载之后,按从上到下(从父类到子类)执行被static修饰的语句;(2)当static语句执行完之后,再执行main方法;(3)如果有语句new了自身的对象,将从上到下执行构造代码块、构造器(两者可以说绑定在一起)。

    下面稍微修改下上面的代码,以便更清晰的说明情况:

    class HelloA {
     
        public HelloA() {
            System.out.println("HelloA");
        }
         
        { System.out.println("I'm A class"); }
         
        static { System.out.println("static A"); }
     
    }
     
    public class HelloB extends HelloA {
        public HelloB() {
            System.out.println("HelloB");
        }
         
        { System.out.println("I'm B class"); }
         
        static { System.out.println("static B"); }
         
        public static void main(String[] args) {
     
            System.out.println("-------main start-------");
            new HelloB();
            new HelloB();
            System.out.println("-------main end-------");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    此时输出结果为:

    static A
    static B
    -------main start-------
    I’m A class
    HelloA
    I’m B class
    HelloB
    I’m A class
    HelloA
    I’m B class
    HelloB
    -------main end-------

    20. getCustomerInfo()方法如下,try中可以捕获三种类型的异常,如果在该方法运行中产生了一个IOException,将会输出什么结果()

    public void getCustomerInfo() {
     
        try {
     
            // do something that may cause an Exception
     
        } catch (java.io.FileNotFoundException ex) {
     
            System.out.print("FileNotFoundException!");
     
        } catch (java.io.IOException ex) {
     
            System.out.print("IOException!");
     
        } catch (java.lang.Exception ex) {
     
            System.out.print("Exception!");
     
        }
     
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    A IOException!

    BIOException!Exception!

    CFileNotFoundException!IOException!

    DFileNotFoundException!IOException!Exception!

    答案:A

    解析:考察多个catch语句块的执行顺序。当用多个catch语句时,catch语句块在次序上有先后之分。从最前面的catch语句块依次先后进行异常类型匹配,这样如果父异常在子异常类之前,那么首先匹配的将是父异常类,子异常类将不会获得匹配的机会,也即子异常类型所在的catch语句块将是不可到达的语句。所以,一般将父类异常类即Exception老大放在catch语句块的最后一个。

    21. 下面代码的运行结果为:()

    import java.io.*;
    import java.util.*;
     
    public class foo{
     
        public static void main (String[] args){
     
            String s;
     
            System.out.println("s=" + s);
     
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    A 代码得到编译,并输出“s=”

    B 代码得到编译,并输出“s=null”

    C 由于String s没有初始化,代码不能编译通过

    D 代码得到编译,但捕获到 NullPointException异常
    答案:C

    解析:开始以为会输出null什么的,运行后才发现Java中所有定义的基本类型或对象都必须初始化才能输出值。

    1. System.out.println(“5” + 2);的输出结果应该是()。

    A 52 B7 C2 D5

    答案:A

    解析:没啥好说的,Java会自动将2转换为字符串。

    22. 指出下列程序运行的结果 ()

    public class Example {
     
        String str = new String("good");
     
        char[] ch = { 'a', 'b', 'c' };
     
        public static void main(String args[]) {
     
            Example ex = new Example();
     
            ex.change(ex.str, ex.ch);
     
            System.out.print(ex.str + " and ");
     
            System.out.print(ex.ch);
     
        }
     
        public void change(String str, char ch[]) {
     
            str = "test ok";
     
            ch[0] = 'g';
     
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    A、 good and abc

    B、 good and gbc

    C、 test ok and abc

    D、 test ok and gbc
    答案:B

    文末

    都是一些非常非常基础的题,是我最近参加各大IT公司笔试后靠记忆记下来的,经过整理献给与我一样参加各大IT校园招聘的同学们,纯考Java基础功底,老手们就不用进来了,免得笑话我们这些未出校门的孩纸们,但是IT公司就喜欢考这些基础的东西。花了不少时间整理,在整理过程中也学到了很多东西,请大家认真对待每一题~~~
    到此这篇关于JAVA题的分享就到这里了,如果看不过瘾本人另外整理收藏了20年多家公司面试知识点整理 ,以及各种Java核心知识点免费分享给大家,想要资料的话请扫描下方二维码

    展开全文
  • 前面文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包数据结构和线程池,Locks锁,Atomic原子) ...下面可能还是会贴很多源代码,其实我拒绝,我只想贴每个方法的代码,但是有时...

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

          多线程爬坑之路-Thread和Runable源码解析 

     

     

    前面大致的了解了Thread的一些方法和属性下面对一些方法进行运用看看具体效果<下面可能还是会贴很多的源代码,其实我是拒绝的,我只想贴每个方法的代码,但是有时候看到一个方法里面有调用了方法,但是笔者有没有给出来,很蛋疼,有种爽到一半的感觉,所以我还是会把它贴出来,希望一次就能挖到底,不论有没有全懂,但至少懂了几分。>

    activeCount():返回当前线程所属线程组的活动线程数

    源代码如下:  

     1  /**
     2      * Returns an estimate of the number of active threads in the current
     3      * thread's {@linkplain java.lang.ThreadGroup thread group} and its
     4      * subgroups. Recursively iterates over all subgroups in the current
     5      * thread's thread group.
     6      *
     7      * <p> The value returned is only an estimate because the number of
     8      * threads may change dynamically while this method traverses internal
     9      * data structures, and might be affected by the presence of certain
    10      * system threads. This method is intended primarily for debugging
    11      * and monitoring purposes.
    12      *
    13      * @return  an estimate of the number of active threads in the current
    14      *          thread's thread group and in any other thread group that
    15      *          has the current thread's thread group as an ancestor
    16      */
    17     public static int activeCount() {
    18         return currentThread().getThreadGroup().activeCount();
    19     }

    这个静态方法先调用了一个currentThread()方法获取当前线程,然后调用了getThreadgroup()获取线程组,最后调用了activeCount()方法获取活动线程数。下面是调用的方法的具体实现,native方法调用的是VM的实现,需要下载VM的源码才能查看,这里先略过。

    /**
         * Returns a reference to the currently executing thread object.
         *
         * @return  the currently executing thread.
         */
        public static native Thread currentThread();
    
    /**
         * Returns the thread group to which this thread belongs.
         * This method returns null if this thread has died
         * (been stopped).
         *
         * @return  this thread's thread group.
         */
        public final ThreadGroup getThreadGroup() {
            return group;
        }
    
    /**
         * Returns an estimate of the number of active threads in this thread
         * group and its subgroups. Recursively iterates over all subgroups in
         * this thread group.
         *
         * <p> The value returned is only an estimate because the number of
         * threads may change dynamically while this method traverses internal
         * data structures, and might be affected by the presence of certain
         * system threads. This method is intended primarily for debugging
         * and monitoring purposes.
         *
         * @return  an estimate of the number of active threads in this thread
         *          group and in any other thread group that has this thread
         *          group as an ancestor
         *
         * @since   JDK1.0
         */
        public int activeCount() {
            int result;
            // Snapshot sub-group data so we don't hold this lock
            // while our children are computing.
            int ngroupsSnapshot;
            ThreadGroup[] groupsSnapshot;
            synchronized (this) {
                if (destroyed) {
                    return 0;
                }
                result = nthreads;
                ngroupsSnapshot = ngroups;
                if (groups != null) {
                    groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
                } else {
                    groupsSnapshot = null;
                }
            }
            for (int i = 0 ; i < ngroupsSnapshot ; i++) {
                result += groupsSnapshot[i].activeCount();
            }
            return result;
        }

    方法的使用:

     1 /**
     2  * thread method test
     3  * @author Ljcx
     4  *
     5  */
     6 public class ThreadMethord implements Runnable{
     7     @Override
     8     public void run() {
     9         System.out.println("");
    10         try {
    11             Thread.sleep(1000);
    12         } catch (InterruptedException e) {
    13             e.printStackTrace();
    14         }
    15     }
    16     
    17     public static void main(String[] args) {
    18         ThreadMethord    tm = new ThreadMethord();
    19         Thread th = new Thread(tm);
    20         th.start();
    21         System.out.println("--活动线程数--"+th.activeCount());
    22         ThreadMethord    tm2 = new ThreadMethord();
    23         Thread th2 = new Thread(tm2);
    24         th2.start();
    25         System.out.println("--活动线程数--"+th2.activeCount());
    26     }
    27 }

    运行结果:

    --活动线程数--2
    --活动线程数--3

    程序启动一共创建了三个线程:main,th,th2,主线程启动main函数,线程th启动,此时的活动线程为main,th.然后创建线程th2并启动。此时活动线程数是main,th,th2.把上面的代码稍微修改一下

     1 public class ThreadMethord implements Runnable{
     2     public void run() {
     3         System.out.println("");
     4         /*try {
     5             Thread.sleep(1000);
     6         } catch (InterruptedException e) {
     7             e.printStackTrace();
     8         }*/
     9     }
    10 
    11     public static void main(String[] args) {
    12         ThreadMethord    tm = new ThreadMethord();
    13         Thread th = new Thread(tm);
    14         th.start();
    15         System.out.println("--活动线程数--"+th.activeCount());
    16         ThreadMethord    tm2 = new ThreadMethord();
    17         Thread th2 = new Thread(tm2);
    18         th2.start();
    19         System.out.println("--活动线程数--"+th2.activeCount());
    20     }
    21 }

    运行结果:

    1 --活动线程数--2
    2 --活动线程数--2

    好像跟预期的结果不一样,只是因为把线程休眠去掉了,那是因为在th2启动的时候th1已经运行结束了。

    基本属性的获取方法:

    方法使用:

     1 public class ThreadMethord implements Runnable{
     2     public void run() {
     3         System.out.println("");
     4         System.out.println("-当前线程的引用--"+ Thread.currentThread());
     5         try {
     6             Thread.sleep(1000);
     7         } catch (InterruptedException e) {
     8             e.printStackTrace();
     9         }
    10     }
    11 
    12     public static void main(String[] args) {
    13         ThreadMethord    tm = new ThreadMethord();
    14         Thread th = new Thread(tm);
    15         th.start();
    16         System.out.println("--活动线程数--"+th.activeCount());
    17         ThreadMethord    tm2 = new ThreadMethord();
    18         Thread th2 = new Thread(tm2);
    19         th2.start();
    20         System.out.println("--活动线程数--"+th2.activeCount());
    21         Thread  [] tarray = new Thread[3]; 
    22         System.out.println("-当前线程的引用--"+ Thread.currentThread());
    23         Thread.enumerate(tarray);//将当前线程的所有活动线程放进数组里
    24         for (Thread thread : tarray) {
    25             System.out.println("--tarray活动线程--"+thread);
    26         }
    27         
    28         System.out.println("--th线程ID--"+th.getId());
    29         System.out.println("--th的线程名--"+ th.getName());
    30         System.out.println("--th的线程优先级--"+ th.getPriority());
    31         System.out.println("--th的线程组--"+ th.getThreadGroup());
    32         
    33         
    34         System.out.println("--th2线程ID--"+th2.getId());
    35         System.out.println("--th2的线程名--"+ th2.getName());
    36         th2.setPriority(6);//设置优先级
    37         System.out.println("--th2的线程优先级--"+ th2.getPriority());
    38         System.out.println("--th2的线程组--"+ th2.getThreadGroup());
    39     }
    40 }

    运行结果:

     1 --活动线程数--2
     2 --活动线程数--3
     3 -当前线程的引用--Thread[main,5,main]
     4 
     5 --tarray活动线程--Thread[main,5,main]
     6 --tarray活动线程--Thread[Thread-0,5,main]
     7 --tarray活动线程--Thread[Thread-1,5,main]
     8 
     9 --th线程ID--10
    10 --th的线程名--Thread-0
    11 --th的线程优先级--5
    12 --th的线程组--java.lang.ThreadGroup[name=main,maxpri=10]
    13 --th2线程ID--11
    14 --th2的线程名--Thread-1
    15 --th2的线程优先级--6
    16 --th2的线程组--java.lang.ThreadGroup[name=main,maxpri=10]
    17 
    18 -当前线程的引用--Thread[Thread-0,5,main]
    19 -当前线程的引用--Thread[Thread-1,6,main]

    可以看到主线程他的引用就是main,优先级是5,所属线程组是main,th和th2他们的引用分别是Thread-0,Thread-1,这是他们的线程名,因为我们在创建现成的时候没有个他初始化名称,所以默认使用Thread-加上线程组内线程创建的序号。(说多了我以为我在胡扯,来看一波源代码)

    源代码:

    //这个初始化方法是我们调用的,可以看到他的命名方式:“Thread-“+nextThreadNum(),这个nextThreadNum方法是一个同步的方法,加了
    //sychnorized锁,返回的是一个私有的静态的int类型的属性,所以他的默认值应该是0,说到这有的小伙伴可能有疑问了,既然默认值(初始值)0,
    //那么这里返回的是threadInitNumber++,那第一个线程名应该是Thread-1,问题又回到了++i和i++的问题了,不多说了。
    public
    Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); } /*初始化方法的四个参数第一个线程组,第二个线程,第三个线程名,第四个是栈大小

     private void init(ThreadGroup g, Runnable target, String name,long stackSize) {

        init(g, target, name, stackSize, null);
      }*/

    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
         return threadInitNumber++;
    }

    getState():获取线程状态

    方法使用:

     1 public class TestMethord2 implements Runnable{
     2     @Override
     3     public void run() {
     4         //获取当前线程的引用
     5         Thread obj = Thread.currentThread();
     6         System.out.println("线程:"+obj.getName()+"的状态:"+obj.getState());//RUNNABLE
     7         try {
     8             Thread.sleep(2000);
     9         } catch (InterruptedException e) {
    10             e.printStackTrace();
    11         }
    12     }
    13     public static void main(String[] args) {
    14         TestMethord2 t1 = new TestMethord2();
    15         TestMethord2 t2 = new TestMethord2();
    16         Thread th1 = new Thread(t1,"th1");
    17         System.out.println(th1.getState());//NEW
    18         th1.start();
    19         System.out.println(th1.getState());//RUNNABLE
    20         //等待线程执行到sleep
    21         try {
    22             Thread.sleep(1000);
    23         } catch (InterruptedException e) {
    24             e.printStackTrace();
    25         }
    26         System.out.println(th1.getState());//TIMES_WAITING
    27         //等待线程th1执行完毕
    28         try {
    29             Thread.sleep(1000);
    30         } catch (InterruptedException e) {
    31             e.printStackTrace();
    32         }
    33         System.out.println(th1.getState());//TERMINATED
    34     }
    35 }

    运行结果:(跑一下代码一目了然可以看到不同的状态)

    1 线程th1的状态:NEW
    2 线程th1的状态:RUNNABLE
    3 RUN线程th1的状态:RUNNABLE
    4 线程th1的状态:TIMED_WAITING
    5 线程th1的状态:TERMINATED

    开始创建的时候状态是:NEW。start之后线程执行,状态是RUNNABLE,此时主线程进入休眠1秒,是为了等待th1进入到休眠状态,当th1进入休眠状态2秒,主线程已经结束了休眠此时在查看th1的状态为TIMED_WAIING,我们再让主线程等待1秒,th1结束了休眠,执行完毕,再次查看th1状态为TERMINATED。

    跟状态相关的方法:

    yield:暂停当前线程,让其他线程先执行。

     1 public class TestMethord3 implements Runnable{
     2 
     3     @Override
     4     public void run() {
     5         System.out.println(Thread.currentThread().getName()+"runing.....");
     6         
     7         for (int i = 0; i <10; i++) {
     8             System.out.println(Thread.currentThread().getName()+":"+i);
     9             if(i==3){
    10                 Thread.yield();
    11             }
    12         }
    13     }
    14     public static void main(String[] args) {
    15         TestMethord3 tm1 = new TestMethord3();
    16         TestMethord3_2 tm2 = new TestMethord3_2();
    17         Thread th1 = new Thread(tm1, "th1");
    18         Thread th2 = new Thread(tm2, "th2");
    19         th1.start();
    20         th2.start();
    21     }
    22 }
    1 public class TestMethord3_2 implements Runnable{
    2     public void run() {
    3         System.out.println(Thread.currentThread().getName()+"runing.....");
    4         for (int i = 0; i < 10; i++) {
    5             System.out.println("------------------"+i);
    6         }
    7     }
    8 }

    运行结果:这个结果每次运行都不一样。

     1 th2runing.....
     2 th1runing.....
     3 ------------------0
     4 ------------------1
     5 ------------------2
     6 ------------------3
     7 ------------------4
     8 ------------------5
     9 ------------------6
    10 th1:0
    11 ------------------7
    12 th1:1
    13 ------------------8
    14 ------------------9
    15 th1:2
    16 th1:3
    17 th1:4
    18 th1:5
    19 th1:6
    20 th1:7
    21 th1:8
    22 th1:9

    按照理想上来说,我们在th1运行到输出3的时候就应该停下来让th2先执行完,th1和th2是我交叉执行应该只发生在th1输出3之前。然而结果并不是如此,多运行几次就会发现,这个yield方法并没有起到应有的作用,这是由于CPU资源充足的情况下两个都能获取到CPU,暂停当前线程的执行可能只是在CPU资源不足的情况下让出CPU资源。(个人理解),但是就算是CPU资源不充足,两个同等优先级的线程在一个暂停之后仍然有同等几率被调度选中分配到资源,所以说这个yield方法同等优先级的情况下出现不管用的几率会更大。

    join:等待某线程终止

     1 public class TestMethord3 implements Runnable{
     2     public void run() {
     3         System.out.println(Thread.currentThread().getName()+"runing.....");
     4         
     5         for (int i = 0; i <10; i++) {
     6             System.out.println(Thread.currentThread().getName()+":"+i);
     7             if(i==3){
     8                 Thread.yield();
     9             }
    10         }
    11     }
    12     public static void main(String[] args) throws InterruptedException {
    13         TestMethord3 tm1 = new TestMethord3();
    14         TestMethord3_2 tm2 = new TestMethord3_2();
    15         Thread th1 = new Thread(tm1, "th1");
    16         Thread th2 = new Thread(tm2, "th2");
    17         th1.start();
    18         th2.start();
    19         th2.join();
    20         System.out.println("th2的状态:"+th2.getState());
    21     }
    22 }
    23 
    24 public class TestMethord3_2 implements Runnable{
    25     public void run() {
    26         System.out.println(Thread.currentThread().getName()+"runing.....");
    27         for (int i = 0; i < 10; i++) {
    28             System.out.println("------------------"+i);
    29         }
    30     }
    31 }

    运行结果:下面是运行四次的结果显示,从结果中可以看出,无论th1,th2怎么运行,最终主线程输出的th2的状态都是TERMINATED,因为这一行输出是放在th2.join()后面的,表示的是主线程要等待th2执行完毕才能继续执行。

    wait(),wait(long million),notify(),notifyAll(),这几个方法继承自Object类.

    wait()和wait(long million):指的是让线程等待,与sleep的不同的是,wait方法会释放CPU,而sleep仍然占有CPU资源。

    notify():指的是唤醒某个线程

    notifyAll() :指的是唤醒所有的线程

    这几个方法需要组合使用,在多个线程运行时涉及到的先后问题,暂时还未研究深入,先放一下。后面会补充上。

     

    通过上面这些方法,基本上了解了线程这个类。除去基本的属性方法,其他的跟状态相关的在复杂的并发线程环境中才能体现他们的作用和价值,也才能展现出使用上的难度,这里所涉及到的不过是九牛一毛,后面继续探索。

    转载于:https://www.cnblogs.com/NextNight/p/6248193.html

    展开全文
  • 1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD 解析:看Java API docs吧:http://docs.oracle.com/javase/7/docs/api/,exit()是System类的方法,如System.exit(0)。 ...
  • 来自:... 下面是我在原文中选择了我比较容易犯错的题   1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD 解析:看Java API docs吧:http://...
  • 一些好java笔试题

    2016-04-19 18:44:10
    1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD 解析:看Java API docs吧:http://docs.oracle.com/javase/7/docs/api/,exit()是System类的方法,如System.exit...
  • java面试3

    2017-09-03 22:23:06
    1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD exit()是System类的方法,如System.exit(0)。2. 下面关于java.lang.Exception类的说法正确的是() A 继承自Throwable B ...
  • JAVA开发岗笔试题集(updating)

    千次阅读 2019-03-08 16:45:34
    1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD 解析:exit()是System类的方法,如System.exit(0)。 2. 下面关于java.lang.Exception类的说法正确的是() A 继承自...
  • 1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD 解析:exit()是System类的方法,如System.exit(0)。   2. 下面关于java.lang....
  • 1. ArrayList下面哪些是Thread类的方法()A.start()B.run()C.exit()D.getPriority()答案:ABDexit()是System类的方法,如System.exit(0)2. 下面关于java.lang.Exception类的说法正确的是()A.继承自ThrowableB....
  • 1:下面哪些是Thread类的方法(); A .start() B.run() C.exit() D.getPriority() 解析:ABD final int getPriority()Returns the pr...
  • 30道Java基础面试题目

    2019-04-11 22:30:58
    1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD 解析:看Java API docs吧:http://docs.oracle.com/javase/7/docs/api/,exit()是System类的方法,如System.exit(0)。 ...
  • 1、下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD,看Java API docs:,exit()是System类的方法,如System.exit(0)。   2、下面程序的运行结果:() public ...
  • 1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD 解析:看Java API docs吧:http://docs.oracle.com/javase/7/docs/api/,exit()是System类的方法,如System.exit(0)。 ...
  • 面试题3与面试题4

    2019-02-19 23:42:00
    1.下面哪些是Thread类的方法() Astart()Brun()Cexit() DgetPriority() start ():这个方法的作用就是通知线程规划器此现场可以运行了。要注意,调用start方法的顺序不代表线程启动的顺序,也就是cpu...
  • java面试题

    2017-11-18 11:26:06
    1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD 解析:看Java API docs吧:http://tool.oschina.net/apidocs/apidoc?api=jdk-zh,exit()是System类的方法,如System.exit...
  • java经典30笔试题

    2018-06-09 11:45:00
    1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD 解析:看Java API docs吧:http://docs.oracle.com/javase/7/docs/api/,exit()是System类的方法,如System.exit(0)。 ...
  • Java笔试题 精品文档 精品文档 收集于网络如有侵权请联系管理员删除 收集于网络如有侵权... 下面哪些是Thread类的方法 A start) B run) C exit) D getPriority) 2下列说法正确的有 A class中的constructor不可省略 B c
  • 1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD 解析:exit()是System类的方法,如System.exit(0)。   2. 下面关于java.lang.Exception类的说法正确的是...
  • Java笔试题

    2017-05-23 23:33:00
    1.下面哪些是Thread类的方法? A.Start() B.run()方法 C.exit()方法 D. getPriority()方法 解析:exit()方法 是 System类的方法 2.GC线程是否为守护线程? 答:是 解析:线程分为(1)守护线程(2)非守护...
  • java2

    2019-09-19 10:30:40
    1.下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD Thread类的getPriority()方法用于检查线程的优先级。 当创建一个线程时,它会为它分配一些优先级。线程的优先级可以由JVM或...
  • 面试题---线程部分

    2017-07-25 19:14:17
    1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD exit()是System类的方法,如System.exit(0)。  int getPriority()  返回线程的优先级。 ...
  • 笔试题目1

    2017-05-25 10:56:27
    1. 下面哪些是Thread类的方法()  A start() B run() C exit() D getPriority()  答案:ABD  解析:看Java API docs吧:http://docs.oracle.com/javase/7/docs/api/,exit()是System类的方法,如System....
  • Java笔试题解答

    千次阅读 2017-04-11 09:45:00
    1. 下面哪些是Thread类的方法() A start() B run() C exit() D getPriority() 答案:ABD 解析:看Java API docs吧:http://docs.oracle.com/javase/7/docs/api/,exit()是System类的方法,如System.exit(0)。 ...
  • 1. 下面哪些是Thread类的方法(ABD) A start() B run() C exit() D getPriority() 2. 下列属于关系型数据库的是( AB) A. Oracle B MySql C IMS D MongoDB 3. Java接口的修饰符可以为( D) A private B ...

空空如也

空空如也

1 2 3 4 5 6
收藏数 111
精华内容 44
关键字:

下面哪些是thread类的方法