java、spring线程池面试题

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

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

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

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

二、线程池的好处?

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

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

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

ExecutorService executorService = Executors.newCachedThreadPool();

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

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:一种定长的线程池,可支持定时以及周期性的执行线程;

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:一个单线程化的线程池,只会通过唯一的工作线程执行任务,保证所有线程都按照指定任务执行;

ExecutorService executorService = Executors.newSingleThreadExecutor();
四、spring提供了哪些线程池?

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

<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();

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的调度权;

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.net/138915.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • MATLAB矩阵运算

    MATLAB矩阵运算矩阵定义MATLAB以矩阵作为数据操作的基本单位,这使得矩阵运算变得非常简捷、方便、高效。矩阵是由m×n个数av(i=1,2,…,m;j=1,2,…,n)排成的m行n列数表,记成:若m=n,则该矩阵为n阶矩阵(n阶方阵)。矩阵创建在键盘上直接按行方式输入矩阵是最方便、最常用的创建数值矩阵的方法,尤其适合较小的简单矩阵。在用此方法创建矩阵时,应当注意以下几点:输入矩阵时要以“[]”为其标识符号,矩阵的所有元素必须都在括号内。 矩阵同行元素之间由空格(个数不限)或…

    2022年6月25日
    26
  • idea 2021.10.3 激活码【2021最新】

    (idea 2021.10.3 激活码)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~1STL5S9V8F-eyJsaWNlbnNlSWQiOi…

    2022年3月27日
    71
  • Oracle数据块原理深入剖析

    Oracle数据块原理深入剖析

    2021年8月30日
    52
  • Java语言对字节数组截取指定长度

    Java语言对字节数组截取指定长度Java通过arraycopy来实现字节数组截取,类比于C语言memcpy,代码如下:System.arraycopy(src,srcPos,dest,destPos,length);参数解析:src:byte源数组srcPos:截取源byte数组起始位置(0位置有效)dest,:byte目的数组(截取后存放的数组)destPos:截取后存放的数组起始位置(0位置有效)…

    2022年6月6日
    205
  • Log4j ConversionPattern参数的格式含义[通俗易懂]

    Log4j ConversionPattern参数的格式含义[通俗易懂]ConversionPattern参数的格式含义格式名含义%c输出日志信息所属的类的全名%d输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy-MM-ddHH:mm:ss},输出类似:2002-10-18-22:10:28%f输出日志信息所属的类的类名%l输出日志事件的发生位置,即输出日志信息的语句处于它所在的类的第几

    2022年8月22日
    6
  • int是什么_uint16范围是多少

    int是什么_uint16范围是多少收到反馈:9位条码更改为12位后,条形码无法自动+1原因:条码的数值超过当前定义的变量的范围调整:将int类型的变量定义为Int64,调整后测试值可自动+1附:Int16值类型表示-32768~+32767之间的整数。Int32值类型表示-2,147,483,648~+2,147,483,647之间的整数。Int64值类型表示-9,223,…

    2022年8月15日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号