java并发编程实战阅读总结(b)

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 阻塞,导致其它线程都无法进行下去,导致性能下降。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/464601.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

公司那些事-关于领导

首先,请允许我将范围限定一下,本文中的领导,并不是指那些了不起的大人物,而是说IT企业中的,我们身边的组长,经理,部长等等,之所以这么限定,原因非常简单,本人只接触过这个层面的领导. 领导也是普通人在我们中间,经常有意无意的对领导提出一些比较高的要求,比如领导应该是技术专…

java io流操作_十个Demo进行讲解Java中IO流的常用操作~

好久不见的IO流对IO流的学习&#xff0c;我记得还是初学Java基础的时候&#xff0c;后来找工作过程中经常看到有些招聘信息中写到熟悉IO流&#xff0c;现在想想IO流&#xff0c;真的是一脸懵逼&#xff0c;不说这么多废话了&#xff0c;IO流这次好好整理一下。说说IO流的类别在…

这些应用仍未兼容安卓新版本,系统升级后将无法使用

8月7日&#xff0c;谷歌正式发布Android 9 Pie&#xff0c;至今已两月有余。近日&#xff0c;华为终端开放实验室对国内主流应用在Android 9 Pie的兼容性进行测试&#xff0c;结果显示&#xff1a;目前TOP3000应用兼容率已经超过95%&#xff0c;但仍有少量应用存在启动失败、闪…

非常郁闷,WinForm中正常显示的自定义控件无法在WebForm中正常显示!

我写了一个自定义控件(Win Control)&#xff0c;此控件在WinForm中运行正常&#xff0c;但在WebForm中无法显示(在WebForm中此控件并不显示为红叉&#xff0c;但是一个对象图标)。由于没有出现权限或安全方面的提示&#xff0c;因此我从头开始一行一行进行比对&#xff0c;最终…

在家过年这两天|多图

这两天收到了很多朋友的新年祝福&#xff0c;在这里回应下&#xff0c;希望看到这篇文章的朋友们新的一年快乐开心&#xff0c;在求学的人学有所成&#xff0c;在工作的朋友们功成名就&#xff0c;家人健康&#xff0c;吃喝不愁……祝你们㏠㏡㏢㏣㏤㏥㏦㏧㏨㏩㏪㏫㏬㏭㏮㏯㏰㏱…

两路归并排序

两路归并排序&#xff08;升序排列&#xff09; (平均/最差)时间复杂度O(NlogN) 将两个有序的单链表合并为一个有序的单链表&#xff0c;默认是按升序排列的。 合并操作是非常适合用递归来完成的一类操作&#xff0c;递归实现将会比迭代实现更加清晰且易于理解。 尽管如此&…

Eclipse下的项目管理插件介绍

前言 最近,一直学习开源项目的代码,难免会碰到各种版本管理器,作为一名在校大学生,学校的课程完全没提及到,靠着自己的摸索,走了不少弯路,写个列表,望对大家有所帮助.顺便提一下,这里只说客户端,至于服务端,自行根据提供的资料学习 CVS 这里eclipse自带就有,也有一段历史,现在的…

算命

今天大年初三&#xff0c;出了太阳变暖很多&#xff0c;我们带着家里的小朋友一起上街吃早餐。因为明天要去阳西&#xff0c;决定去外婆家看看&#xff0c;在超时买了点东西&#xff0c;走回车上刚好看到路边有算命先生&#xff0c;我就想着来计算一下。我先是问了记算一次多少…

back log

1*你应该备份日志 BACKUP LOG 数据库名 TO DISKc:\aalogbak WITH INIT,NO_TRUNCATE 这样你的日志清空也备份了&#xff0c;日志也清空了&#xff0c;你可以压缩了 在维护日志备份序列时&#xff0c;调度 BACKUP LOG 语句按间隔发生&#xff0c;以使事务日志不致增长到超过预期的…

java loadlibrary_java – System.loadLibrary不起作用.链中的第二个lib的UnsatisfiedLinkError...

我有通过JNI使用cpp共享库libclient.so的java程序Client.class.libclient.so构建为共享并使用cpp共享库libhttp.so.libclient.so和libhttp.so放在文件夹/ home / client / lib64中Client.class放在/ home / client / bin中客户端可以加载库> System.load和环境变量LD_LIBRAR…

tcp的滑动窗口

今天阅读了TCP中滑动窗口部分的内容&#xff0c;总结如下&#xff1a; 滑动窗口&#xff1a;又叫缓冲区&#xff0c;是两台主机间传送数据时的缓冲区。每台TCP/IP主机支持两个滑动窗口&#xff1a;一个用于接收数据&#xff0c;另一个用于发送数据。 窗口尺寸表示计算机可能缓…

嵌入式行业那些坑与出路

嵌入式的坑烧钱嵌入式的学习十分烧钱&#xff0c;这就让人有点望而却步。我是做DSP起步的&#xff0c;更是能体会到嵌入式绝对是一个拿钱搭梯子的学习行业。在我的学习过程中身边有不少的人投向了CS行业&#xff0c;也就是纯软件开发&#xff0c;比如网页、手机应用、数据库等。…

入行后第二份工作的一些感悟

这是我毕业后进入的第二家公司。也是我工作的第二个年头。转眼之间在新公司已经度过半年的时间了。内心还是有些许的感慨。 工作的内容和上家公司是差不多的&#xff0c;主要是做windows方面的基础架构和应用的维护&#xff0c;例如AD、exchange、lync、ISA、虚拟化等等&a…

poj2631

求一棵树的直径&#xff0c;所谓直径就是树上距离最远的两个点&#xff01; 树形动归&#xff0c;每个点的为根的子树的最长向下链和次长链的和&#xff01; 当然也可以二次深搜&#xff01; ————————————————————————————————————————…

原来做的一个语义搜索软件的界面

今天得知NGW&#xff08;New Generation Web&#xff0c;关于语义网络方面的&#xff09;课程及实验作业成绩已公布&#xff0c;急去查看&#xff0c;但与想象中相去甚远。 罢了&#xff0c;凡事但求尽力而为&#xff0c;末了问心无愧即可&#xff0c;其它种种皆是虚幻。 附&am…

tcp为什么需要3次握手和3次握手的过程

网络上关于tcp连接时的3次握手相关的文章很多&#xff0c;在此不再重复&#xff0c;个人总结如下&#xff0c;如有不正确之处请给予指正。 tcp“三次握手”的目的是: 为了防止已经失效的请求报文段突然又传送到了服务器端&#xff0c;因而产生错误。 tcp的3次握手过程: (1)、…

C使用FILE指针文件操作

文件 文件的基本概念 所谓“文件”是指一组相关数据的有序集合。这个数据集有一个名称&#xff0c;叫做文件名。例如源程序文件、目标文件、可执行文件、库文件 (头文件)等。文件通常是驻留在外部介质(如磁盘等)上的&#xff0c;在使用时才调入内存中来。从不同的角度可对文件作…

java 守护线程 run_java守护线程(后台线程)

/*1.让各个对象或类相互灵活交流2.两个线程都冻结了&#xff0c;就不能唤醒了&#xff0c;因为根据代码要一个线程活着才能执行唤醒操作&#xff0c;就像玩木游戏3.中断状态就是冻结状态4.当主线程退出的时候&#xff0c;里面的两个线程都处于冻结状态&#xff0c;这样就卡住了…

2年质保期刚过就翘辫子,这是什么骚设计?

1.终于又坏了一件自从开始写聊聊身边的嵌入式这个系列&#xff0c;便常常有一个邪恶的想法在脑袋里盘旋&#xff0c;总盼着家里哪件电器赶紧出点毛病。你知道&#xff0c;如果不把一个东西拆的七零八落&#xff0c;覆水难收&#xff0c;那是不能满足咱们的好奇心的。都说念念不…

剑指offer---用两个栈实现队列

题目&#xff1a;用两个栈实现队列 要求&#xff1a;用两个栈来实现一个队列&#xff0c;完成队列的Push和Pop操作。 队列中的元素为int类型。 1 class Solution2 {3 public:4 void push(int node) {5 6 }7 8 int pop() {9 10 } 11 12 priva…