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不可以中断;

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

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