当前位置: 首页 > news >正文

网站开发好学分销订单管理系统

网站开发好学,分销订单管理系统,网站建设q a,专业团队ppt模板线程 线程与进程的区别是什么#xff1f; 进程指的是应用程序在操作系统中执行的副本#xff08;系统分配资源的最小单位#xff09;#xff0c;线程是程序执行的最小单位#xff1b;进程使用独立的数据空间#xff0c;而线程共享进程的数据空间。 线程状态图 多线程会…线程 线程与进程的区别是什么 进程指的是应用程序在操作系统中执行的副本系统分配资源的最小单位线程是程序执行的最小单位进程使用独立的数据空间而线程共享进程的数据空间。 线程状态图 多线程会带来哪些性能问题 调度开销一般线程数往往大于CPU核心数这样操作系统再执行线程时就会出现上下文切换从而产生一定性能开销协作开销为了保证线程之间共享变量的线程安全有可能会禁用编译器和CPU的重排序等优化还可能会频繁的将工作内存刷新到主内存主内存再同步给工作内存这些开销都是单线程下不存在的。 JMM内存模型 什么是JMM内存模型 JMM 是和多线程相关的一组规范需要各个 JVM 的实现来遵守 JMM 规范JMM 与处理器、缓存、并发、编译器有关。它解决了 CPU 多级缓存、处理器优化、指令重排等导致的结果不可预期的问题。 什么是指令重排序有什么好处 重排序是指编译器、JVM 或者 CPU 为了提高执行效率对于实际指令执行的顺序进行调整重排序通过减少执行指令从而提高整体的运行速度。 什么是内存可见性问题 共享变量的值已经被第 1 个线程修改了但是其他线程却看不到。 主内存和工作内存的关系是什么 所有的变量都存储在主内存中同时每个线程拥有自己独立的工作内存而工作内存中的变量的内容是主内存中该变量的拷贝线程不能直接读 / 写主内存中的变量但可以操作自己工作内存中的变量然后再同步到主内存中这样其他线程就可以看到本次修改主内存是由多个线程所共享的但线程间不共享各自的工作内存如果线程间需要通信则必须借助主内存中转来完成。 什么是 happens-before 关系 如果第一个操作和第二个操作之间满足 happens-before 关系那么我们就说第一个操作对于第二个操作一定是可见的 volatile volatile的作用是什么 保证内存可见性以及多线程之间操作的有序性 volatile如何保证可见性 volatile变量修饰的共享变量在进行写操作的时候会多出一个lock前缀的汇编指令当对其进行写操作时JVM就会向处理器发送一条Lock前缀的指令把这个变量所在的缓存行的数据写回到系统内存。然后处理器会根据MESI缓存一致性协议来保证多CPU下的各个高速缓存中的数据的一致性。 volatile是否可以保证原子性 volatile是一种轻量级的同步机制它主要有两个特性 保证共享变量对所有线程的可见性禁止指令重排序优化 同时需要注意的是在多线程场景下如果仅仅是赋值操作volatile可以保证原子性但是像num这种复合操作取值、计算、赋值volatile无法保证其原子性。 synchronized synchronized有几种使用方式 类、方法、代码块 synchronized的底层实现原理是什么 每个Object对象中都内置了一个Monitor监视器通过指令Monitor.enter和Monitor.exit进行加锁和释放锁加锁失败的线程会被加入到一个同步队列中当锁被释放时再重新竞争锁。 JVM对synchronized做了哪些优化 无锁 - 偏向锁 - 轻量级锁 - 重量级锁 描述锁升级的过程 偏向锁升级轻量级锁当一个对象持有偏向锁一旦第二个线程访问这个对象如果产生竞争偏向锁升级为轻量级锁。轻量级锁升级重量级锁一般两个线程对于同一个锁的操作都会错开或者说稍微等待一下自旋另一个线程就会释放锁。但是当自旋超过一定的次数或者一个线程在持有锁一个在自旋又有第三个来访时轻量级锁膨胀为重量级锁重量级锁使除了拥有锁的线程以外的线程都阻塞防止CPU空转。 wait和notify为什么需要在synchronized里面 wait方法的语义有两个一个是释放当前的对象锁、另一个是使得当前线程进入阻塞队列而这些操作都和监视器是相关的所以wait必须要获得一个监视器锁。而对于notify来说也是一样它是唤醒一个线程既然要去唤醒首先得知道它在哪里所以就必须要找到这个对象获取到这个对象的锁然后到这个对象的等待队列中去唤醒一个线程。 wait/notify 和 sleep 方法的区别是什么 wait 方法必须在 synchronized 保护的代码中使用而 sleep 方法并没有这个要求在同步代码中执行 sleep 方法时并不会释放 monitor 锁但执行 wait 方法时会主动释放 monitor 锁sleep 方法中会要求必须定义一个时间时间到期后会主动恢复而对于没有参数的 wait 方法而言意味着永久等待直到被中断或被唤醒才能恢复它并不会主动恢复wait/notify 是 Object 类的方法而 sleep 是 Thread 类的方法。 为什么 wait/notify/notifyAll 被定义在 Object 类中而 sleep 定义在 Thread 类中 因为 Java 中每个对象都有一把称之为 monitor 监视器的锁锁信息保存在对象头中wait/notify/notifyAll 都是锁级别的操作所以把它们定义在 Object 类中是最合适如果把 wait/notify/notifyAll 方法定义在 Thread 类中会带来很大的局限性比如一个线程可能持有多把锁以便实现相互配合的复杂逻辑假设此时 wait 方法定义在 Thread 类中如何实现让一个线程持有多把锁呢又如何明确线程等待的是哪把锁呢既然我们是让当前线程去等待某个对象的锁自然应该通过操作对象来实现而不是操作线程。 synchronize与volatile的区别是什么 volatile 可以看作是一个轻量版的 synchronized比如一个共享变量如果自始至终只被各个线程赋值和读取而没有其他操作的话那么就可以用 volatile 来代替 synchronized 或者代替原子变量足以保证线程安全volatile无法保证对“i”一类复合操作包括取值、计算、赋值的原子性和互斥性它保证了变量间的可见性并禁用了指令重排序synchronize没有禁用指令重排序这也是单例double check模式对象必须用volatile修饰的原因。 AQS 什么是AQS内部组成有哪些 AQS提供了一个FIFO双向队列可以看做是一个用来实现锁以及其他需要同步功能的框架。AQS主要由三部分组成 第一个是 state它是一个数值在不同的类中表示不同的含义往往代表一种状态第二个是一个FIFO的队列该队列用来存放阻塞状态的线程第三个是“获取/释放”的相关方法需要利用 AQS 的工具类根据自己的逻辑去实现。 AQS的底层结构具体是怎样的 底层是由head节点、tail节点、双向链表组成的双向队列head与tail节点主要负责节点的出队与入队时间复杂度O(1);之所以使用双向链表而不是单向链表是因为AQS考虑到高并发的场景下节点的状态时刻都有可能发生变化当前节点的一些动作需要依赖前序节点的状态例如 只有当前节点的prev节点为head时才有资格参与锁竞争当前节点进入阻塞之前需要判断该节点的prev节点的状态是否为SIGNAL节点的线程释放或被取消会通知后继节点。 AQS解决了哪些问题 状态的原子性管理线程的阻塞与解除阻塞队列的管理。 AQS中state的应用有哪些 对于ReentrantLock持有锁的线程每次lock重入state1每次unlockstate -1只有state 0才表示彻底释放锁其它线程才可以获取对于Semaphoreacquire 方法代表获取许可此时能不能获取许可取决于state的值是否足够如果足够state值会减掉对应的许可数量如果不够则会进入阻塞release方法代表释放许可state值会增加直到定义的上限值对于CountDownLatchawait方法会判断state值是否为0不为0则进入阻塞等待直到其它线程通过countDown方法将state减为0才会执行对于CyclicBarrier线程调用await方法state会1如果state值小于初始设置的阈值线程阻塞等待直到state累加等于该阈值所有等待的线程会一起释放同时state会清0。 Lock Lock和synchronized的区别 类别synchronizedLock存在层次Java的关键字在jvm层面上是一个接口锁的释放1、以获取锁的线程执行完同步代码释放锁2、线程执行发生异常jvm会让线程释放锁。必须在finally中释放锁不然容易造成线程死锁锁的获取假设A线程获得锁B线程等待。如果A线程阻塞B线程会一直等待。Lock有多种获取锁的方式如lock、tryLock锁状态无法判断只能阻塞可以判断;tryLock();tryLock(long time, TimeUnit unit);可避免死锁。锁类型可重入非公平不可中断可重入可公平两者皆可可中断lockInterruptibly();功能功能单一API丰富tryLock();tryLock(long time, TimeUnit unit);可避免死锁。 描述Lock的加锁的全流程 当一个线程成功地获取了同步状态或者锁其他线程将无法获取转而被构造成为尾节点并加入AQS同步队列这个过程通过CAS来保证的线程安全。同步队列遵循FIFO首节点是获取同步状态成功的节点首节点的线程在释放同步状态时将会唤醒后继节点而后继节点将会在获取同步状态成功时将自己设置为首节点。设置首节点是通过获取同步状态成功的线程来完成的由于只有一个线程能够成功获取到同步状态因此设置头节点的方法并不需要使用CAS来保证它只需要将首节点设置成为原首节点的后继节点并断开原首节点的next引用即可。 公平锁与非公平锁的区别如何实现的 非公平锁在获取锁的时候会先通过CAS进行抢占而公平锁则不会公平锁会优先从同步队列中去唤醒这样就保证了先到先得的顺序非公平锁的效率更高因为唤醒线程的过程是比较耗时的非公平锁会利用这部分时间完成其它任务但有可能造成锁饥饿。 对比悲观锁乐观锁的优点和缺点都有哪些? 乐观锁优点 悲观锁需要遵循下面三种模式一锁、二读、三更新即使在没有冲突的情况下执行也会非常慢乐观锁本质上不是锁它只是一个判断逻辑资源冲突少的情况下它不会产生任何开销 乐观锁缺点 在并发量比较高的情况下有些线程可能会一直尝试修改某个资源但由于冲突比较严重一直更新不成功这时候就会给 CPU 带来很大的压力并发量大可以考虑通过分段锁的方式优化例如LongAdder或者直接使用悲观锁无法解决ABA问题意思是指在 CAS 操作时有其他的线程现将变量的值由 A 变成了 B然后又改成了 A当前线程在操作时发现值仍然是 A于是进行了交换操作。大部分场景下ABA问题不会给业务带来影响可以通过引入版本号的方式解决。 线程池 线程池的核心参数有哪些 public ThreadPoolExecutor( int corePoolSize, // 核心线程数 int maximumPoolSize, // 最大线程数 long keepAliveTime, // 临时线程等待时间 TimeUnit unit, // 时间单位 BlockingQueueRunnable workQueue, // 阻塞队列 RejectedExecutionHandler handler) // 拒绝策略线程池执行任务的流程是什么 拒绝策略有哪些 AbortPolicy默认丢弃任务并抛出RejectedExecutionException异常DiscardPolicy丢弃任务但是不抛出异常DiscardOldestPolicy抛弃队列中等待最久的任务然后把当前任务加入到队列中CallerRunsPolicy提交任务的主线程调用任务的run()方法绕过线程池直接执行这种方法不会发生数据丢失并且可以延缓任务提交的速度缓解线程池压力。 ForkJoinPool有什么特点 它每个线程都有一个自己的双端队列来存储分裂出来的子任务避免了公共队列的阻塞采用工作窃取模式空闲线程 t1 可以帮助繁忙线程 t0 完成工作这也是队列设计为双端队列的目的t0是按LIFO的顺序处理任务而t1 在steal t0任务时会按照FIFO的顺序ForkJoinPool 非常适合用于递归的场景例如树的遍历、最优路径搜索等场景。 ForkJoinPool与ThreadPoolExecutor区别是什么 ForkJoinPool中的每个线程都会有一个队列而ThreadPoolExecutor只有一个队列并根据queue类型不同细分出各种线程池ForkJoinPool能够使用数量有限的线程来完成非常多的具有父子关系的任务ThreadPoolExecutor中根本没有什么父子关系任务ForkJoinPool在多任务且任务分配不均是有优势但是在单线程或者任务分配均匀的情况下效率没有ThreadPoolExecutor高。 JDK提供的线程池用到了哪些阻塞队列 LinkedBlockingQueueFixedThreadPool 和 SingleThreadExector 的默认队列容量为 Integer.MAX_VALUE可以认为是无界队列不会生成多于核心线程数的线程SynchronousQueueCachedThreadPool的默认队列是一种没有容量的阻塞队列。与FixedThreadPool正好相反CachedThreadPool为了尽可能创建新的线程执行任务它的最大线程数是 Integer.MAX_VALUE队列容量为0DelayedWorkQueueScheduledThreadPool的默认队列可以周期性执行任务或延迟一定时间执行任务DelayedWorkQueue会按照延迟的时间长短对任务排序内部数据结构是堆二叉树。 CPU核心数和线程数的关系是什么 如果是CPU密集型任务例如加密、解密、编译、压缩、计算等任务一般可以考虑线程数为CPU核心数的1~2倍具体还应该参考压测结果如果是IO密集型任务可参考公式线程数 CPU 核心数 *1 线程平均等待时间 / 线程平均工作时间。 队列 队列常见api的区别 有哪些常见的阻塞队列 ArrayBlockingQueue 最典型的有界队列其内部是用数组存储元素的不会扩容利用 ReentrantLock 实现线程安全 LinkedBlockingQueue 内部用链表实现的 BlockingQueue容量默认就为整型的最大值 Integer.MAX_VALUE一般称为无界队列 SynchronousQueue 容量为0的传递队列存数据会阻塞知道有人来存同理取数据也会阻塞直到有人来存 PriorityBlockingQueue 无界的优先级阻塞队列有初始容量可扩容可以通过自定义类实现 compareTo() 方法来指定元素排序规则或者初始化时通过构造器参数 Comparator 来指定排序规则内部的数据结构是堆 DelayQueue 无界的延迟队列DelayQueue 内部使用了 PriorityQueue 的能力来进行排序。 ArrayBlockingQueue的实现原理是什么 ArrayBlockingQueue 实现并发同步的原理就是利用 ReentrantLock 和它的两个 Condition读操作和写操作都需要先获取到 ReentrantLock 独占锁才能进行下一步操作进行读操作时如果队列为空线程就会进入到读线程专属的 notEmpty 的 Condition 的队列中去排队等待写线程写入新的元素同理如果队列已满这个时候写操作的线程会进入到写线程专属的 notFull 队列中去排队等待读线程将队列元素移除并腾出空间。 阻塞队列和非阻塞队列在实现上有哪些区别 阻塞队列最主要是利用了 ReentrantLock 以及它的 Condition 来实现而非阻塞队列则是利用 CAS 方法实现线程安全。 多线程工具类 CountDownLatch与CyclicBarrier的区别是什么 作用对象不同CyclicBarrier 要等固定数量的线程都到达了栅栏位置才能继续执行而 CountDownLatch 只需等待数字倒数到 0也就是说 CountDownLatch 作用于事件但 CyclicBarrier 作用于线程可重用性不同CountDownLatch 在倒数到 0 并且触发门闩打开后就不能再次使用了除非新建一个新的实例而 CyclicBarrier 可以重复使用并不需要重建实例。CyclicBarrier 还可以随时调用 reset 方法进行重置如果重置时有线程已经调用了 await 方法并开始等待那么这些线程则会抛出 BrokenBarrierException 异常。执行动作不同CyclicBarrier 有执行动作 barrierAction而 CountDownLatch 没这个功能。 Future Future与CompletableFuture区别 通过Future接收异步任务时主线程需要通过get()方法去阻塞轮询获取结果如果是多个任务则需要等到所有任务完成之后才能做后续操作而通过CompletableFuture接收异步任务时无需等待所有任务全部完成每个任务都可以通过thenAccept、thenApply、thenCompose等方式将前面的结果交给另一个异步事件来处理最后还可以通过allOf或anyOf等方法来汇总结果。 FutureTask的实现原理是什么 当我们通过Future接收异步任务时底层是通过其实现类FutureTask的run方法来执行任务的run方法主要完成了以下流程 检查线程的状态执行用户定义的call方法执行结束后设置返回值或异常并更新线程状态然后唤醒队列中阻塞等待获取结果的线程 当其它线程通过future.get获取结果时 首先根据状态判断任务是否完成如果已经完成则直接返回如果没有完成则会阻塞当前线程并将其加入到阻塞队列如果没有指定阻塞时间则一直阻塞知道任务完成唤醒当任务完成时阻塞的线程会被唤醒拿到结果后返回 ThreadLocal ThreadLocal的作用与使用场景是什么 ThreadLocal 用作保存每个线程独享的对象为每个线程都创建一个副本这样每个线程都可以修改自己所拥有的副本, 而不会影响其他线程的副本确保了线程安全。ThreadLocal 用作每个线程内需要独立保存信息以便供其他方法更方便地获取该信息的场景。每个线程获取到的信息可能都是不一样的前面执行的方法保存了信息后后续方法可以通过 ThreadLocal 直接获取到避免了传参类似于全局变量的概念。 ThreadLocal与Thread的关系是什么 一个 Thread 里面只有一个ThreadLocalMap 而在一个 ThreadLocalMap 里面却可以有很多的 ThreadLocal每一个 ThreadLocal 都对应一个 value。因为一个 Thread 是可以调用多个 ThreadLocal 的所以 Thread 内部就采用了 ThreadLocalMap 这样 Map 的数据结构来存放 ThreadLocal 和 value。 ThreadLocal与Synchronized的区别是什么 ThreadLocal 是通过让每个线程独享自己的副本避免了资源的竞争。synchronized 主要用于临界资源的分配在同一时刻限制最多只有一个线程能访问该资源。ThreadLocal 并不是用来解决共享资源的多线程访问的问题因为每个线程中的资源只是副本并不共享。因此ThreadLocal适合作为线程上下文变量简化线程内传参。 ThreadLocal为什么可能产生内存泄漏如何避免 通过ThreadLocalMap的源码可以看到Entry中的key被定义为弱引用类型当发生GC时key会被直接回收无需手动清理。而value属于强引用类型被当前的Thread对象关联所以说value的回收取决于Thread对象的生命周期。 如果说一个线程执行完毕线程Thread随之被释放那么value便不存在内存泄漏的问题。然而我们一般会通过线程池的方式来复用Thread对象来节省资源这就会导致一个Thread对象的生命周期会非常长随着任务的执行value就有可能越来越多且无法释放最终导致内存泄漏。 因此我们在使用完ThreadLocal变量后要手动调用remove()方法来清理ThreadLocalMap一般在finally代码块中。 子线程如何共享主线程的ThreadLocal变量 因为ThreadLocal变量保存在当前线程的成员变量ThreadLocalMap中新创建子线程后无法再次使用父线程的ThreadLocal变量为了解决子线程复用主线程ThreadLocal的问题Thread类中还有另一个ThreadLocalMapinheritableThreadLocals里面保存的是InheritableThreadLocal它是ThreadLocal的子类Thread类初始化时会默认从父线程继承inheritableThreadLocals因此我们可以用InheritableThreadLocal代替ThreadLocal实现父子线程共享线程变量的问题。
http://www.pierceye.com/news/222766/

相关文章:

  • 化妆品网站建设方案做咩有D网站响网吧上不了
  • 网站 迁移房地产销售基础知识大全
  • 门户网站建设汇报材料网站开发与制作中期报告
  • 网站建设可以自己弄吗知乎做网站必须要服务器吗
  • 怎么制作自己的小程序专业seo整站优化
  • 做网站是干什么用的苏宁易购网站上的营销页面
  • 浪网站制作网站开发是无形资产
  • 做阿里巴巴网站可以贷款吗seo如何快速排名百度首页
  • 公司做网站都咨询哪些问题网站平台建设视频教学
  • 西安电子商务网站建设网站里面的链接怎么做
  • 郑州陆港开发建设有限公司网站58招商加盟项目
  • 徐州高端网站建设个人网站设计首页界面
  • 山西企业建站系统平台关键词 优化 网站
  • 地板网站建设方案有什么做美食的网站
  • 网站建设丶金手指专业网站幻灯片 字段
  • 网站开发技术总结干完房产中介整个人废了
  • iis建站安装wordpress对网站建设的评价语
  • 网站开发网站建设公司二手房网
  • 72建站网如何建设一个药材网站做网站的费用 可以抵扣吗
  • 四川通信建设工程有限公司网站做企业网站需要服务器么
  • 福田建网站费用烟台招远网站建设
  • 上海网站开发建设电话丹东市做网站
  • 外贸网站 免费模板 使用 zencart做新闻类网站
  • 呼和浩特网站推广大德通网站建设
  • 携程旅行网站建设上海城市建设大学网站
  • 360网站收录做网站设计用什么软件
  • 微信html5模板网站最新网站建设软件有哪些
  • 芝麻开门网站建设无极电影网怎样下载电影
  • 网站开发 书籍首页关键词优化价格
  • 网站建设建站流程方案百度一下你就知道下载安装