网站制作排名,响应式网站一般做几个尺寸,深圳app开发公司鑫酷,有祥云网站一、多线程
1、什么是线程?线程和进程的区别?
2、创建线程有几种方式 #xff1f;
3、Runnable 和 Callable 的区别#xff1f;
4、如何启动一个新线程、调用 start 和 run 方法的区别#xff1f;
5、线程有哪几种状态以及各种状态之间的转换#xff1f;
6、线程…一、多线程
1、什么是线程?线程和进程的区别?
2、创建线程有几种方式
3、Runnable 和 Callable 的区别
4、如何启动一个新线程、调用 start 和 run 方法的区别
5、线程有哪几种状态以及各种状态之间的转换
6、线程相关的基本方法
7、 wait()和 sleep()的区别
二、线程池
1、为什么需要线程池
2、线程池的分类高薪常问 3、核心参数高薪常问
4、线程池的原理高薪常问 5、拒绝策略
6、如何关闭线程池
7、线程池中阻塞队列的作用为什么是先添加列队而不是先创建最
大线程
8、线程池中线程复用原理 一、多线程
1、什么是线程? 线程和进程的区别? 线程是进程的一个实体是 cpu 调度和分派的基本单位是比进程更小的可以独立运行 的基本单位。 进程具有一定独立功能的程序关于某个数据集合上的一次运行活动是操作系统进行资源 分配和调度的一个独立单位。 特点线性程的划分尺度小于进程这使多线程程序拥有高并发进程在运行时各自内存单 元相互独立线程之间 内存共享这使多线程编程可以拥有更好的性能和用户体验。 2、创建线程有几种方式 继承 Thread 类并重写 run 方法创建线程实现简单但不可以继承其他类实现 Runnable 接口并重写 run 方法。避免了单继承局限性编程更加灵活实现 解耦。实现 Callable 接口并重写 call 方法创建线程。可以获取线程执行结果的返回值 并且可以抛出异常。使用线程池创建使用 java.util.concurrent.Executor 接口 3、Runnable 和 Callable 的区别 主要区别 Runnable 接口 run 方法无返回值Callable 接口 call 方法有返回值支持泛型 Runnable 接口 run 方法只能抛出运行时异常且无法捕获处理Callable 接口 call 方法允许抛出异常可以获取异常信息 4、如何启动一个新线程、调用 start 和 run 方法的区别 线程对象调用 run 方法不开启线程。仅是对象调用方法。 线程对象调用 start 开启线程并让 jvm 调用 run 方法在开启的线程中执行 调用 start 方法可以启动线程并且使得线程进入就绪状态而 run 方法只是 thread 的一个普通方法还是在主线程中执行。 5、线程有哪几种状态以及各种状态之间的转换 1第一是 new- 新建状态。在生成线程对象 并没有调用该对象的 start 方法这 是线程处于创建状态。 2第二是 Runnable- 就绪状态。当 调用了线程对象的 start 方法之后该线程就 进入了就绪状态但是此时线程调度程序还没有把该线程设置为当前线程此时处于就绪状 态。 3第三是 Running- 运行状态。线程调度程序将处于就绪状态的线程 设置为当前线 程此时线程就进入了运行状态 开始运行 run 函数当中的代码。 4第四是 阻塞状态。阻塞状态是线程因为某种原因放弃 CPU 使用权暂时停止运 行。直到线程进入就绪状态才有机会转到运行状态。阻塞的情况分三种 等待 – 通过调用线程的 wait() 方法让线程等待某工作的完成。超时等待 – 通过调用线程的 sleep() 或 join()或发出了 I/O 请求时线程会进 入到阻塞状态。当 sleep()状态超时、join()等待线程终止或者超时、或者 I/O 处理完毕时 线程重新转入就绪状态。同步阻塞 – 线程在获取 synchronized 同步锁失败(因为锁被其它线程所占用) 它会进入同步阻塞状态。 5第五是 dead- 死亡状态: 线程执行完了或者因异常退出了 run()方法该线程结 束生命周期. 6、线程相关的基本方法 线程等待wait 调用该方法的线程进入 WAITING 状态只有等待另外线程的通知或被中断才会返回 需要注意的是调用 wait()方法后会释放对象的锁。因此wait 方法一般用在同步方法或 同步代码块中。 线程睡眠sleep sleep 导致当前线程休眠与 wait 方法不同的是 sleep 不会释放当前占有的 锁,sleep(long)会导致线程进入 TIMED-WATING 状态而 wait()方法会导致当前线程进 入 WATING 状态. 线程让步yield yield 会使当前线程让出 CPU 执行时间片与其他线程一起重新竞争 CPU 时间片。 一般情况下优先级高的线程有更大的可能性成功竞争得到 CPU 时间片但这又不是绝对 的有的操作系统对 线程优先级并不敏感。 线程中断interrupt 中断一个线程其本意是给这个线程一个通知信号会影响这个线程内部的一个中断标 识位。这个线程本身并不会因此而改变状态(如阻塞终止等) Join 等待其他线程终止 join() 方法等待其他线程终止在当前线程中调用一个线程的 join() 方法则当前 线程转为阻塞状态回到另一个线程结束当前线程再由阻塞状态变为就绪状态等待 cpu 的宠幸. 线程唤醒notify Object 类中的 notify() 方法唤醒在此对象监视器上等待的单个线程如果所有线 程都在此对象上等待则会选择唤醒其中一个线程选择是任意的并在对实现做出决定 时发生线程通过调用其中一个 wait() 方法在对象的监视器上等待直到当前的线程放 弃此对象上的锁定才能继续执行被唤醒的线程被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争。类似的方法还有 notifyAll() 唤醒再次监视器上等 待的所有线程。 7、 wait()和 sleep()的区别 1来自不同的类 wait():来自 Object 类 sleep():来自 Thread 类 2关于锁的释放 wait():在等待的过程中会释放锁 sleep():在等待的过程中不会释放锁 3使用的范围 wait():必须在同步代码块中使用 sleep():可以在任何地方使用 4是否需要捕获异常 wait():不需要捕获异常 sleep():需要捕获异常 二、线程池
1、为什么需要线程池 在实际使用中线程是很占用系统资源的如果对线程管理不完善的话很容易导致系统问题。 因此在大多数并发框架中都会使用线程池来管理线程使用线程池管理线程主要有如下好 处 1使用线程池可以重复利用已有的线程继续执行任务避免线程在创建销毁时造成的消 耗 2由于没有线程创建和销毁时的消耗可以提高系统响应速度 3通过线程可以对线程进行合理的管理根据系统的承受能力调整可运行线程数量的大 小等 2、线程池的分类高薪常问 1newCachedThreadPool创建一个可进行缓存重复利用的线程池 2newFixedThreadPool创建一个可重用固定线程数的线程池以共享的无界队列 方式来运行这些线程线程池中的线程处于一定的量可以很好的控制线程的并发量 3newSingleThreadExecutor创建一个使用单个 worker 线程的 Executor 以无 界队列方式来运行该线程。线程池中最多执行一个线程之后提交的线程将会排在队列中以 此执行 4newSingleThreadScheduledExecutor创建一个单线程执行程序它可安排在给 定延迟后运行命令或者定期执行 5newScheduledThreadPool创建一个线程池它可安排在给定延迟后运行命令或 者定期的执行 6newWorkStealingPool创建一个带并行级别的线程池并行级别决定了同一时刻 最多有多少个线程在执行如不传并行级别参数将默认为当前系统的 CPU 个数 3、核心参数高薪常问 corePoolSize核心线程池的大小 maximumPoolSize线程池能创建线程的最大个数 keepAliveTime空闲线程存活时间 unit时间单位为 keepAliveTime 指定时间单位 workQueue阻塞队列用于保存任务的阻塞队列 threadFactory创建线程的工程类 handler饱和策略拒绝策略 4、线程池的原理高薪常问 线程池的工作过程如下 当一个任务提交至线程池之后 1线程池首先判断核心线程池里的线程是否已经满了。如果不是则创建一个新的工作 线程来执行任务。否则进入 2判断工作队列是否已经满了倘若还没有满将线程放入工作队列。否则进入 3. 3判断线程池里的线程是否都在执行任务。如果不是则创建一个新的工作线程来执行。 如果线程池满了则交给饱和策略来处理任务。 5、拒绝策略 ThreadPoolExecutor.AbortPolicy系统默认 丢弃任务并抛出RejectedExecutionException 异常让你感知到任务被拒绝了我们可以根据业务逻辑选 择重试或者放弃提交等策略。 ThreadPoolExecutor.DiscardPolicy 也是丢弃任务但是不抛出异常相对而言存在 一定的风险因为我们提交的时候根本不知道这个任务会被丢弃可能造成数据丢失。 ThreadPoolExecutor.DiscardOldestPolicy 丢弃队列最前面的任务然后重新尝试执 行任务重复此过程通常是存活时间最长的任务它也存在一定的数据丢失风险。 ThreadPoolExecutor.CallerRunsPolicy既不抛弃任务也不抛出异常而是将某些任务 回退到调用者让调用者去执行它。 6、如何关闭线程池 关闭线程池可以通过 shutdown 和 shutdownNow 两个方法 原理遍历线程池中的所有线程然后依次中断 1、shutdownNow 首先将线程池的状态设置为 STOP,然后尝试停止所有的正在执行和 未执行任务的线程并返回等待执行任务的列表 2、shutdown 只是将线程池的状态设置为 SHUTDOWN 状态然后中断所有没有正 在执行任务的线程 7、线程池中阻塞队列的作用为什么是先添加列队而不是先创建最
大线程 1一般的队列只能保证作为一个有限长度的缓冲区如果超出了缓冲长度就无法保留当 前的任务了阻塞队列通过阻塞可以保留住当前想要继续入队的任务。 阻塞队列可以保证任务队列中没有任务时阻塞获取任务的线程使得线程进入 wait 状态 释放 cpu 资源。阻塞队列自带阻塞和唤醒的功能不需要额外处理无任务执行时,线程池利用阻塞队列的 take 方法挂起从而维持核心线程的存活、不至于一直占用 cpu 资源 2在创建新线程的时候是要获取全局锁的这个时候其它的就得阻塞影响了整体效率。 就好比一个企业里面有 10 个core正式工的名额最多招 10 个正式工要是任务超过 正式工人数task core的情况下工厂领导线程池不是首先扩招工人还是这 10 人但是任务可以稍微积压一下即先放到队列去代价低。10 个正式工慢慢干迟早 会干完的要是任务还在继续增加超过正式工的加班忍耐极限了队列满了就的招外 包帮忙了注意是临时工要是正式工加上外包还是不能完成任务那新来的任务就会被领 导拒绝了线程池的拒绝策略。 8、线程池中线程复用原理 线程池将线程和任务进行解耦线程是线程任务是任务摆脱了之前通过 Thread 创建 线程时的一个线程必须对应一个任务的限制。 在线程池中同一个线程可以从阻塞队列中不断获取新任务来执行其核心原理在于线程池 对 Thread 进行了封装并不是每次执行任务都会调用 Thread.start() 来创建新线程而 是让每个线程去执行一个“循环任务”在这个“循环任务”中不停检查是否有任务需要被 执行如果有则直接执行也就是调用任务中的 run 方法将 run 方法当成一个普通的 方法执行通过这种方式只使用固定的线程就将所有任务的 run 方法串联起来。