面试题之并发相关专栏四

一、Java中的线程池是如何实现的?

  • 在Java中,所谓的线程池中的线程,其实是被抽象为了一个静态内部类Worker,基于AQS实现,存放在线程池的HashSet workers成员变量中;
  • 需要执行的任务存放在成员变量workQueue中,workQueue是一个阻塞队列;
  • 线程池的基本思想就是:从workQueue队列中不断取出需要执行的任务,放在Workers中进行执行;

二、如何自定义线程池?

自定义线程池是通过new ThreadPoolExecutor()指定对应的参数创建,下面给出一个示例:

private static ExecutorService getExecutorService() {
        return new ThreadPoolExecutor(
                5,  //常驻核心线程的数量
                5, //线程池中能够容纳同时执行的最大线程数
                0L, //多余的空闲线程的存活时间
                TimeUnit.MILLISECONDS, //时间单位:毫秒
                new LinkedBlockingQueue<>(5), //阻塞队列
                Executors.defaultThreadFactory(), //默认线程池生产工厂
                new ThreadPoolExecutor.AbortPolicy() //拒绝策略
        );
    }

三、线程池中的线程是怎么创建的?它是一开始就随着线程池的启动创建好的么? 

线程池默认初始化后不启动worker,等待有请求时才启动。

线程池执行流程:

  

文字描述:任务进来时,首先执行判断,判断常驻核心线程是否处于空闲状态,如果不是,核心线程就先就执行任务,如果核心线程已满,则判断任务队列是否有地方存放该任务,如果有,就将任务保存在任务队列中,等待执行,如果满了,在判断最大可容纳的线程数,如果没有超出这个数量,就创建非核心线程执行任务,如果超出了,就调用handler实现拒绝策略。 

四、如何在Java线程池中提交线程任务?

  • execute():  ExecutorService.execute()方法接收一个runnable示例,用来执行一个任务;
  • submit():  ExecutorService.submit() 方法返回的是Future对象,可以使用get()获取线程执行结果;

五、什么是Java的内存模型,Java中各个线程是怎么彼此看到对方变量的?

Java的内存模型定义了程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出这样的底层细节。此处的变量包括实例字段、静态字段和构成数组对象的元素,但是不包括局部变量和方法参数,因为这些是线程私有,不会被共享,不存在资源竞争问题。

Java中定义了主内存和工作内存的概念:所有的变量都存储在主内存中,每条线程还有自己的工作内存,保存了被该线程使用到的变量的主内存的副本拷贝,线程对变量的所有操作(读取、赋值)都必须在自己的工作内存中完成,不能直接读写主内存中的变量,不同的线程之间也无法直接访问对方工作内存的变量,线程之间变量值的传递需要通过主内存来完成。

发布了250 篇原创文章 · 获赞 112 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/Weixiaohuai/article/details/105332185