网站膜拜销售,厦门小微企业网站建设补贴,加强专业建设的思路和建议,商城网站建设公司排行5、Executor框架
Executor框架是并发集合java.util.concurrent中的一个成员。 Executor为灵活且强大的异步任务执行框架提供了基础#xff0c;还提供了对生命周期的支持#xff0c;以及统计信息、应用管理机制和性能监视等机制。Executor 最早是为了解决生产者-消费者模式而…5、Executor框架
Executor框架是并发集合java.util.concurrent中的一个成员。 Executor为灵活且强大的异步任务执行框架提供了基础还提供了对生命周期的支持以及统计信息、应用管理机制和性能监视等机制。Executor 最早是为了解决生产者-消费者模式而引入的。提交任务相当是生产者执行任务相当是消费者。线程池(翻译的文档)线程池和工作者队列密切相关工作者线程的任务从工作队列中获取一个任务执行任务然后返回线程池并等待下一个任务。Executors类里面提供了一些静态工厂生成一些常用的线程池。newSingleThreadExecutor创建一个单线程的线程池。这个线程池只有一个线程在工作也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。newFixedThreadPool创建固定大小的线程池。每次提交一个任务就创建一个线程直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变如果某个线程因为执行异常而结束那么线程池会补充一个新线程。newCachedThreadPool创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程那么就会回收部分空闲60秒不执行任务的线程当任务数增加时此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制线程池大小完全依赖于操作系统或者说JVM能够创建的最大线程大小。newScheduledThreadPool创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。newSingleThreadScheduledExecutor创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。线程池Executor任务拒绝策略(翻译的文档)java.util.concurrent.RejectedExecutionHandler描述的任务操作。第一种方式直接丢弃DiscardPolicy第二种丢弃最旧任务DiscardOldestPolicy第三种直接抛出异常AbortPolicy第四种任务将有调用者线程去执行(CallerRunsPolicy)生命周期(翻译的文档)java.util.concurrent.ExecutorService 接口对象来执行任务该接口对象通过工具类java.util.concurrent.Executors的静态方法来创建。 Executors此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。ExecutorService扩展了Executor并添加了一些生命周期管理的方法。一个Executor的生命周期有三种状态运行 关闭 终止。Executor创建时处于运行状态。当调用ExecutorService.shutdown()后处于关闭状态isShutdown()方法返回true。这时不应该再想Executor中添加任务所有已添加的任务执行完毕后Executor处于终止状态isTerminated()返回true。shutdown()执行平缓的关闭过程不再接受新的任务同时等待已经提交的任务执行完成。shutdownNow();执行粗暴的关闭过程尝试取消所有运行中的任务并且不再启动队列中尚未开始启动的任务。awaitTermination 这个方法有两个参数一个是timeout即超时时间另一个是unit即时间单位。这个方法会使线程等待timeout时长当超过timeout时间后会监测ExecutorService是否已经关闭若关闭则返回true否则返回false。一般情况下会和shutdown方法组合使用。ExecutorService service Executors. newFixedThreadPool(3); for ( int i 0; i 10; i) { System. out.println( 创建线程 i); Runnable run new Runnable() { Override public void run() { System. out.println( 启动线程); } }; // 在未来某个时间执行给定的命令 service.execute(run); } // 关闭启动线程 service.shutdown(); // 每隔1秒监测一次ExecutorService的关闭情况. service.awaitTermination(1, TimeUnit. SECONDS); System. out.println( all thread complete); System. out.println(service.isTerminated());
6、锁机制引入的死锁、活锁和饥饿 加锁机制的目的是保证线程安全但如果过度使用锁会导致死锁等。我们使用线程池和信号量来限制对资源的限制。但这些被限制的行为可能导致死锁。 死锁进程之间互相争夺资源导致系统无法向前运行的一种僵死状态如果没有外力作用下系统很难继续向前运行。请参考我的博客多线程。 饥饿当线程无法访问到它所需要的资源而不能继续执行时就会发生饥饿。引发饥饿的最常见资源就是CUP的时钟周期。 活锁liveLock是进程的状态还在发生变化但是不再继续向前运行的状态。 7、线程的开销 (1)、上下文切换。cpu在做线程切换的时候需要保存当前线程执行的上下文并且新调度进来的线程执行上下文设置为当前上下文。 发生越多的上下文切换增加了调度开销并因此降低吞吐量。 (2)、内存数据的同步。synchronized发生隐式锁竞争的地方带来的开销会影响其它线程的性能。 (3)、阻塞。当在锁上发生竞争时竞争失败的线程会阻塞即所谓的竞态条件。JVM通过循环不断的尝试获取锁直到成功。或者通过操作系统挂起阻塞的线程。 如果时间短采用等待方式如果时间长才适合采用线程挂起的方式。串行操作降低可伸缩性并行切换上下文也会降低性能。 在锁发生竞争时会同时导致上面两种问题因此减少锁的竞争能够提高性能和收缩性。在并发程序中 对可伸缩性最主要的威胁就是独占方式的资源锁。两个因素将影响锁上面发生竞争的可能性锁的请求频率以及每次持有该锁的时间。 如果两者的乘积很小那么大多数获取锁操作都不会发生竞争。 三种方式可以降低锁的竞争程度 (1)、降低锁的请求频率。 降低线程请求锁的频率可以通过锁分解和锁分段等技术来实现。即减小锁的粒度。如果一个锁同时需要保护好几个状态变量那么可以把这个锁分解成多个锁并且每个锁只保护一个状态变量从而提高可伸缩性并最终降低每个锁的请求频率。但是使用的锁越多发生死锁的风险也会越高。 (2)、减少锁的持有时间。 减少被锁部分的加锁时间。缩小锁的范围(快进快出)可以将一些与锁无关的代码移出同步代码块尤其是开销较大的操作以及可能被阻塞的操作比如I/O 操作。 (3)、减少使用独占锁并发容器读-写锁不可变对象以及原子变量。
独占锁是一种悲观的技术。它假设最坏的情况发生(如果不加锁,其它线程会破坏对象状态)即使没有发生最坏的情况仍然用锁保护对象状态 8、原子变量原子性采用锁技术会导致对锁的竞争导致系统性能降低。
当一个线程正在等待锁时它不能做任何其他事情。如果一个线程在持有锁的情况下被延迟执行那么所有需要这个锁的线程都无法执行下去。原子性是指cpu在执行每一段代码时是不能被中断的。对除了long和double的基本类型的数据的简单操作都是原子的。例如a 1; return a原子变量支持不用锁保护就能原子性更新操作其底层用CAS实现。一共有12个原子变量可分为4组标量类、更新器类、数组类以及复合变量类。最常用的原子变量就是标量类AtomicInteger、AtomicLong、AtomicBoolean以及AtomicReference。所有类型都支持CAS。
JVM对CAS的支持 CAS有3个操作数内存值V旧的预期值A要修改的新值B。当且仅当预期值A和内存值V相同时将内存值V修改为B否则什么都不做。 CAS典型使用模式是首先从V中读取A并根据A计算新值B然后再通过CAS以原子方式将V中的值由A变成B只要在这期间没有任何线程将V的值修改为其他值。 转载的博文http://blog.csdn.net/csujiangyu/article/details/44002463 说明比较并交换的行为而不是性能的代码 public class SimulatedCAS { private int value; public synchronized int getValue() { return value; } public synchronized int compareAndSwap(int expectedValue, int newValue) { int oldValue value; if (value expectedValue) value newValue; return oldValue; } } 使用比较并交换实现计数器 public class CasCounter { private SimulatedCAS value; public int getValue() { return value.getValue(); } public int increment() { int oldValue value.getValue(); while (value.compareAndSwap(oldValue, oldValue 1) ! oldValue) oldValue value.getValue(); return oldValue 1; } } 非阻塞同步机制 非阻塞算法的定义一个线程的失败或者挂起不会影响其它线程的失败或者挂起。非阻塞算法提供比synchronized机制更高的性能和可收缩性。可以使多个线程在竞争相同的数据时候不会发生阻塞。基于锁的算法中可能会出现各种活跃性的障碍比如I/O 阻塞导致其它线程都无法进行下去导致性能下降。