前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java、spring线程池面试题

java、spring线程池面试题

作者头像
全栈程序员站长
发布2022-08-23 16:16:18
1970
发布2022-08-23 16:16:18
举报

大家好,又见面了,我是你们的朋友全栈君。

一、什么是进程,什么是线程?

进程是一个程序运行的实例,一个进程拥有自己独立的地址空间,一般来说,一个进程是无法访问另一个进程的资源的,可以通过管道、套接字来实现; 线程是操作系统运行调度的最小单元,它被包含在进程里面,是进程中实际的运行单位;

二、线程池的好处?

1.通过new Thread来创建线程池会比较耗时,性能差,当我们在使用线程的时候,有可能会出现(创建线程+销毁线程)的时长>线程执行(业务逻辑)的时长; 2.线程缺乏统一管理,可能会出现无限制的创建线程,线程之间相互竞争,争夺资源而导致系统崩溃; 3.缺乏更多的管理功能,比如定时执行、定期执行、线程中断; 相比较于new Thread,创建线程的好处在于: 1.重用已存在的线程,避免线程新建和消亡产生的开销。 2.可以控制最大并发数,避免同时多个线程执行,争夺资源,导致系统崩溃; 3.拥有更多的功能,比如:定时执行,定期执行,控制并发数,单线程等功能;

三、java提供了哪些线程池?

java是通过ExecuterService来提供线程池的,他提供了四种线程池的实现; 1.newCacheThreadPool:一种可缓存的线程池,若线程池长度超出处理需要,可灵活回收空闲线程,当没有空闲线程可回收时,则创建新线程,线程池长度无限制;

代码语言:javascript
复制
ExecutorService executorService = Executors.newCachedThreadPool();

2.newFixedThreadPool:一种定长的线程池,通过控制线程最大并发数,超过了线程的最大并发数,则在队列中等待其他线程的释放;

代码语言:javascript
复制
ExecutorService executorService = Executors.newFixedThreadPool(3);
        for(int i=0; i<10; i++){
            final int thred = i;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+":"+thred);
                }
            });
        }

3.newScheduleThreadPool:一种定长的线程池,可支持定时以及周期性的执行线程;

代码语言:javascript
复制
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);
        //以当前时间开始,每三秒间隔周期性的执行任务
        executorService.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("3 s");
            }
        }, 3, TimeUnit.SECONDS);

        //一秒后开始执行,此后每三秒执行任务
        executorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd hh:mm:ss"));
            }
        }, 1, 3, TimeUnit.SECONDS);

4.newSingleThreadPool:一个单线程化的线程池,只会通过唯一的工作线程执行任务,保证所有线程都按照指定任务执行;

代码语言:javascript
复制
ExecutorService executorService = Executors.newSingleThreadExecutor();
四、spring提供了哪些线程池?

spring提供的七种类型的线程池,其中我们主要使用的是ThreadPoolTaskExecutor,配置方式如下:

代码语言:javascript
复制
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
          <!-- 线程池维护线程的最少数量 -->
          <property name="corePoolSize" value="5" />
          <!-- 允许的空闲时间 -->
          <property name="keepAliveSeconds" value="200" />
          <!-- 线程池维护线程的最大数量 -->
          <property name="maxPoolSize" value="10" />
          <!-- 缓存队列 -->
         <property name="queueCapacity" value="20" />
         <!-- 对拒绝task的处理策略 -->
         <property name="rejectedExecutionHandler">
             <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
         </property>
 </bean>

主要包括以下几个参数: corePoolSize:线程池最少维护的数量 keepAliveSeconds:允许的空闲时间 maxPoolSize:线程池维护现场的最大数量 queueCapacity:缓存队列 rejectedExecutionHandler:对拒绝task的处理策略

execute(Runable)方法执行过程 1.当线程池里的线程数量小于corePoolSize时,即使当前线程池里面的线程都出于空闲状态,也会新建线程来处理任务; 2.当线程池里的线程数量等于corePoolSize时,若缓存队列里面的数据未满则任务放入缓存队列里面等待 3.当线程池里的线程数量大于corePoolSize小于maxPoolSize时,若缓存队列里面的数量已满,则新建线程 4.当线程池里面的线程数量大于corePoolSize时,若线程处于空闲状态并且空闲时间超过keepAliveSeconds时,将会回收线程,可以动态的控制线程池里面的线程数量 5.当线程池里面的线程数等于maxPoolSize,并且缓存队列已满,则通过rejectedExecutionHandler设置的处理策略来处理任务; 拒绝策略有以下几种处理方式: 1.ThreadPoolExecutor.AbortPolicy:舍弃任务,并抛出异常 2.ThreadPoolExecutor.DiscardPolicy:舍弃任务,不抛出异常 3.ThreadPoolExecutor.DiscardOldestPolicy:丢弃缓存队列最旧(也就是排在队列前面的任务)的任务,并将此任务添加到缓存队列 4.ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务,(直接在executor处理的线程中执行该任务,若线程已关闭则舍弃该任务)

五、如何判断一个线程是否拥有锁?

java.lang.Thread类下面有一个方法holdsLock(Obj),返回true则表示拥有对象Obj的锁;

六、java中的wait和sleep有什么区别?

这两个方法都会使线程暂停一段时间,wait方法用于线程间的通信,当条件为真并且其他线程被唤醒时会释放锁,而sleep只会释放cpu资源或者让当前线程停止一段时间,但是不会释放锁; sleep是线程里面的方法,而wait是Object的方法; sleep不需要被唤醒,而如果wait没有设置时间,则需要被唤醒(notify); wait依赖synchronized关键字,而sleep不需要;

七、如何保证三个线程按顺序执行?

可以通过线程自带的join方法,join方法指的是等上一个线程执行完成后在执行,比如说三个线程,thread1,thread2,thread3,按1、2、3顺序执行的话,我们可以设置thread3.join(thread2.join(thread1)); 或者通过并发类来控制,比如CountDownLatch();

代码语言:javascript
复制
final Thread thread1 =  new Thread(new Runnable() {

           @SneakyThrows
           @Override
           public void run() {
               Thread.sleep(1000);
               System.out.println(Thread.currentThread().getName()+":"+1);
           }
       });
        final Thread thread2 =  new Thread(new Runnable() {

            @SneakyThrows
            @Override
            public void run() {
                thread1.join();
                System.out.println(Thread.currentThread().getName()+":"+2);
            }
        });
        Thread thread3 =  new Thread(new Runnable() {

            @SneakyThrows
            @Override
            public void run() {
                thread2.join();
                System.out.println(Thread.currentThread().getName()+":"+3);
            }
        });

        thread1.start();
        thread2.start();
        thread3.start();
八、Thread的yield方法有什么用?

Thread执行了yield之后会让掉当前的cpu时间片,然后去重新争夺cpu调度权,可能会获取到cpu调度权并继续执行,也可能获取不到;注意:只会和当前线程同级或者更高级的cpu去竞争cpu的调度权;

代码语言:javascript
复制
public static void thread6(){

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i=0; i<100; i++){
                    System.out.println(Thread.currentThread().getName()+":"+i);
                    if(i%20==0){
                        Thread.yield();
                    }
                }
            }
        };

        Thread thread1 = new Thread(runnable, "A");
        Thread thread2 = new Thread(runnable, "B");
//        thread1.setPriority(1);
//        thread2.setPriority(5);
        thread1.start();
        thread2.start();
    }
九、sleep和yield的区别和相同点

sleep和yeild都可以让当前线程暂停,不过sleep可以指定暂停时间,yield则依赖cpu时间片的划分 sleep和yield都不会释放锁 sleep可以中断,yield不可以中断;

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/138915.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年5月6,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、什么是进程,什么是线程?
  • 二、线程池的好处?
  • 三、java提供了哪些线程池?
  • 四、spring提供了哪些线程池?
  • 五、如何判断一个线程是否拥有锁?
  • 六、java中的wait和sleep有什么区别?
  • 七、如何保证三个线程按顺序执行?
  • 八、Thread的yield方法有什么用?
  • 九、sleep和yield的区别和相同点
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档