Java常见面试题1

本文内容仅可做复习使用,知识点结构无序。不建议做系统学习使用

文章目录

  • 1.线程创建方式?
      • 继承Thread类
      • 实现Runnable接口
      • 使用Callable和FutureTask
      • 通过线程池创建线程
  • 线程池
  • 新生代老年代
  • 动态年龄判断机制
  • 双亲委派模型
  • 类加载器
  • JVM内存模型
  • JVM内存结构

1.线程创建方式?

继承Thread类

继承Thread类,创建一个新的线程类
同时重写run()方法,将需要并发执行的业务代码编写在run()方法中

实现Runnable接口

(1) 定义一个新类实现Runnable接口。
(2) 实现Runnable接口中的run()抽象方法,将线程代码逻辑存放在该run()方法中。
(3) 通过Thread类创建线程对象,将Runnable实例作为实际参数传递给Thread类的构造器,由Thread构造器将该Runnable实例赋值给自己的target执行目标属性。
(4) 调用Thread实例的start()方法启动线程。
(5) 线程启动之后,线程的run()方法将被JVM执行,该run()方法将调用target属性的run()方法,从而完成Runnable实现类中业务代码逻辑的并发执行。

使用Callable和FutureTask

  1. 前面两种方式(继承Thread和实现Runnable)有一个共同的缺陷:不能获取异步执行的结果。这是一个比较大的问题,很多场景都需要获取异步执行的结果,通过Runnable无法实现,是因为它的run()方法不支持返回值
  2. 为了解决异步执行的结果问题,Java语言在1.5版本之后提供了一种新的多线程创建方法:通过Callable接口和FutureTask类相结合创建线程。
  3. 通过FutureTask类和Callable接口的联合使用可以创建能够获取异步执行结果的线程,具体步骤如下:
    (1) 创建一个Callable接口的实现类,并实现其call()方法,编写好异步执行的具体逻辑,可以有返回值。
    (2) 使用Callable实现类的实例构造一个FutureTask实例。
    (3) 使用FutureTask实例作为Thread构造器的target入参,构造新的Thread线程实例
    (4)调用Thread实例的start()方法启动新线程,启动新线程的run()方法并发执行。其内部的执行过程为:启动Thread实例的run()方法并发执行后,会执行FutureTask实例的run()方法,最终会并发执行Callable实现类的call()方法。
    (5) 调用FutureTask对象的get()方法阻塞性地获得并发线程的执行结果。

通过线程池创建线程

在高并发的场景中,断然不能频繁进行线程实例的创建与销毁,而是需要对已经创建好的线程实例进行复用,这就涉及线程池的技术。Java中提供了一个静态工厂来创建不同的线程池,该静态工厂为Executors工厂类

public class CreateDemo {
    private static ExecutorService threadpool = Executors.newFixedThreadPool(3);
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1、执行Runnbale类型的target目标实例,无返回
        threadpool.execute(new RunnableTaskDemo());

        //2、 执行Runnbale类型的target目标实例,无返回,内部类形式
        threadpool.execute(new Runnable() {
            @Override
            public void run() {
                for(int i=0;i<3;i++){
                    System.out.println(Thread.currentThread().getName()+" 轮次:"+i);

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }       
        });

        // 3、提交Callable执行目标实例,有返回
        Future future = threadpool.submit(new CallableTaskDemo());
        System.out.println("异步执行的结果为:" + future.get());
    }
}

public class RunnableTaskDemo implements Runnable {
    @Override
    public void run() {
        for(int i=0;i<3;i++){
            System.out.println(Thread.currentThread().getName()+" 轮次:"+i);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class CallableTaskDemo implements Callable {
    @Override
    public Long call() throws Exception {
        Long startTime = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName()+" 线程开始运行");
        for(int i=0;i<3;i++){
            System.out.println(Thread.currentThread().getName()+" 轮次:"+i);
            Thread.sleep(1000);
        }
        Long used = System.currentTimeMillis()-startTime;
        System.out.println(Thread.currentThread().getName()+" 线程结束运行");
        return used;
    }
}

线程池

详见:https://blog.csdn.net/qq_43478694/article/details/123385279

新生代老年代

动态年龄判断机制

双亲委派模型

类加载器

JVM内存模型

JVM内存结构

你可能感兴趣的:(面试题目,java,面试,开发语言)