http://www.cnblogs.com/sarafill/archive/2011/05/18/2049461.html

    *
    线程
    1.一个进程中的线程是在同一个地址空间中执行的
    2.多个线程可以同时访问相同对象,并且它们从同一堆栈中分配对象(意味着您必须确保线程之间不相互干涉)


    *
    线程安全的类
    1.对该类的对象的任何顺序的操作(公共字段的读写、公共方法的调用)都不应该使对象处于无效状态
    2.要成为线程安全的类,在从多个线程访问时,它必须继续正确运行,而不管运行时环境执行哪些线程的调度和交叉,且无需对部分调用代码执行任何其他同步


    线程安全类举例:
    1.AWT和Swing:GUI 组件注册的监听器
    2.TimerTask:Timer 线程中执行 TimerTask 事件
    3.Servlet和JavaServer Page技术:Servlet 容器可以创建多个线程,在多个线程中同时调用给定 servlet,从而进行多个请求
    4.RMI:远程类必须是线程安全的


    *
    java.util.concurrent 包
    添加了多个新的线程安全集合类(ConcurrentHashMap、CopyOnWriteArrayList 和 CopyOnWriteArraySet)。
    一些集合已经是线程安全的(Hashtable 和 Vector),通过同步的封装工厂(Collections.synchronizedMap()、synchronizedList() 和 synchronizedSet()),其余的集合均可表现为线程安全的。
    并发性能
    HashMap<HashTable<CurrentHashMap


    *
    迭代器
    1.java.util 包中的集合类都返回 fail-fast 迭代器(即:在迭代过程中不更改集合,否者抛出ConcurrentModificationException)
    2.java.util.concurrent 集合返回的迭代器称为弱一致的(weakly consistent)迭代器。(允许迭代过程中有线程对集合进行更改)

    注意:java.util.concurrent集合类通过每次添加或删除元素时创建支持数组的新副本,避免了fail-fast 迭代器的问题.
    java.util.concurrent集合类,还提高了并发性


    Hashtable 和 Collections.synchronizedMap 通过同步每个方法获得线程安全。
    (这意味着当一个线程执行一个 Map 方法时,无论其他线程要对 Map 进行什么样操作,都不能执行,直到第一个线程结束才可以。)
    ConcurrentHashMap 允许多个读取几乎总是并发执行,读和写操作通常并发执行,多个同时写入经常并发执行。
    (结果是当多个线程需要访问同一 Map 时,可以获得更高的并发性,ConcurrentHashMap 实例中的同步不锁定映射进行独占使用,应该是使用拷贝的方式实现的)
    在大多数情况下,ConcurrentHashMap 是 Hashtable或 Collections.synchronizedMap(new HashMap()) 的简单替换。


    *
    Executor框架
    java.util.concurrent包中包含灵活的线程池实现,但是更重要的是,它包含用于管理实现 Runnable 的任务的执行的整个框架 -- Executor 框架。
    Executor实现:每个实现都实现不同的执行策略(执行策略:定义何时在哪个线程中运行任务,执行任务可能消耗的资源级别(线程、内存等等),以及如果执行程序超载该怎么办)
    ThreadPoolExecutor 的实例,是高度可定制的
    线程池可能会死锁

    线程数=N*(1+WT/ST) 【n为cpu的个数、wt为线程平均等待时间、st为线程平均运行时间】
    Future接口:允许表示已经完成的任务、正在执行过程中的任务或者尚未开始执行的任务(可以用来尝试取消未完成的任务)
    CompletionService:将执行服务与类似 Queue 的接口组合(CompletionService 接口包含用来提交将要执行的任务的 submit() 方法和用来询问下一完成任务的 take()/poll() 方法)
    Semaphore:Semaphore 类实现标准 Dijkstra 计数信号。


    *
    守护进程:
    独立于控制终端、周期性执行某任务。Linux上的多数服务就是使用守护进程实现的。
    thread.setDaemon(true);//创建守护线程


    *
    1.同步块比同步方法产生的字节码多
    2.以线程为单位存储信息时,使用ThreadLocal
    3.每个线程都会维护一份变量的副本,如果变量是使用volatile标记,那么线程每次使用变量时都会再取一遍。
    4.使用volatile并不能保证变量操作的原子性
    5.使用原子类java.util.concurrent.atomic,保证对集合操作的同步性


    *
    线程池
    1.避免系统资源不足导致崩溃
    2.消除了创建线程带来的延迟
    3.带线程池的工作队列实现:
    public class WorkQueue
    {
    private final int nThreads;
    private final PoolWorker[] threads;
    private final LinkedList queue;
    public WorkQueue(int nThreads)
    {
    this.nThreads = nThreads;
    queue = new LinkedList();
    threads = new PoolWorker[nThreads];
    for (int i=0; i<nThreads; i++) {
    threads[i] = new PoolWorker();
    threads[i].start();
    }
    }
    public void execute(Runnable r) {
    synchronized(queue) {
    queue.addLast(r);
    queue.notify();
    }
    }
    private class PoolWorker extends Thread {
    public void run() {
    Runnable r;
    while (true) {
    synchronized(queue) {
    while (queue.isEmpty()) {
    try
    {
    queue.wait();
    }
    catch (InterruptedException ignored)
    {
    }
    }
    r = (Runnable) queue.removeFirst();
    }
    // If we don't catch RuntimeException,
    // the pool could leak threads
    try {
    r.run();
    }
    catch (RuntimeException e) {
    // You might want to log something here
    }
    }
    }
    }
    }
    4.各种线程池可能存在线程泄露的风险(如:线程发生异常,线程池类没有处理;某些线程永久等待)
    5.无需编写自己的线程池,而应该使用util.concurrent中的类
    6.处理生命周期很短的线程应该使用线程池


    *
    对阻塞线程的条件需要使用循环来判断,即:
    while(queue.isEmpty()){
    queue.wait();
    }
    因为:线程可能被唤醒时,条件仍然不满足,所以需要循环判断,使用while(来自effictive java)


    *
    在Java5.0及以上版本中,线程的全部六种状态都以枚举类型的形式定义在java.lang.Thread类中了,代码如下:
    public enum State {
    NEW, //新建状态,new命令之后
    RUNNABLE, //可运行状态,start()之后
    BLOCKED, //阻塞状态,等待同步锁
    WAITING, //等待状态,wait(),join(),park()之后
    TIMED_WAITING, //定时等待状态,wait(),join(),packNanos()带时间参数之后
    TERMINATED; //死亡状态,run()中代码全部运行完
    }


    *
    同步方法:需要获取的锁对象是,此同步方法所在的对象本身
    静态同步方法:需要获取的锁对象是,此同步方法所在的类本身(其实也是一个对象,即Class的对象)
    同步块:可以自定义需要获取的锁对象

    注:如果锁对象被锁(指:所对象被某个线程获取),那么其他的线程就无法获取此锁对象,从而无法进入同步区域


    *
    lock()与unlock()
    类似声明式事物,把需要同步的代码放在lock()与unlock()之间即可。

    注:Lock比synchronized能更细分需要同步的代码,即可以根据需要定义不同的Lock对象。


    *
    非阻塞算法(乐观算法)
    https://www.ibm.com/developerworks/cn/java/j-jtp11234/
    在 JDK 5.0 之前,如果不使用本机代码,就不能用 Java 语言编写无等待、无锁定的算法。(即:需要自己使用C来写本地方法,用来实现原子类)
    在 java.util.concurrent.atomic 包中添加原子变量类之后,这种情况才发生了改变。
    原子变量类可以认为是 volatile 变量的泛化,它扩展了可变变量的概念,来支持原子条件的比较并设置更新。
    无论是直接的还是间接的,几乎 java.util.concurrent 包中的所有类都使用原子变量,而不使用同步。


    *
    Future模式
    0.Future表示异步计算的结果
    1.顾名思义:是对未来的一种凭证
    2.在GUI中用的比较多,即:虚拟代理模式
    3.是被广泛运用的并发设计模式,java5并发包有此实现
    4.Future是线程的执行结果票据
    5.Future的原理是当你申请资源(计算资源或I/O资源)时,立即返回一个虚拟的资源句柄,当真正使用的时候,再将虚拟的句柄转化成真正的资源,相当于预获取
    6.Future模式只有在并行运算的框架内才有意义。把一个大的耗时的事,分成多个小的耗时的事,最终耗时等于小的事里开销最大的时间(所谓流水线技术)
    7.Future模式的时机:大并发,阻塞会降低服务端吞吐量,此时使用future减少客户端的请求对服务器通道的占用

    Futrue实现
    1.jdk中的接口java.util.concurrent.Future
    2.FutureTask是Future的一个实现,需要与线程池Excutor一起使用,才能完成Future模式的意义(因此它们都在jdk的并发包里)
    3.ExecutorService.submit(new Callable(){})能构造出一个futrue对象


    *
    协程coroutine(微线程/纤程)
    0.定义
    yield/resume
    协程源自Simula和Modula-2语言
    corutine不是对线程的一种简化或者跨平台模拟
    与子例程一样,协程也是一种程序组件
    子例程是协程的特例
    1.线程和协同程序的主要不同在于:
    在任一指定时刻只有一个协同程序在运行
    协程是用户空间线程,操作系统其存在一无所知,所以需要用户自己去做调度
    协程可以通过yield来调用其它协程,协程之间不是调用者与被调用者的关系,而是彼此对称、平等的。
    2.优点
    跨平台,跨体系架构
    无需线程上下文切换的开销
    无需原子操作锁定及同步的开销
    3.各种语言的coroutine
    Gevent也是一个基于coroutine的python网络开发框架
    Lua里的协程
    JavaScript(ECMA-262 6th Edition)
    Scala
    4.协程的发展过程:
    并发: 一开始大家想要同一时间执行那么三五个程序,大家能一块跑一跑。特别是UI什么的,别一上计算量比较大的玩意就跟死机一样。于是就有了并发,从程序员的角度可以看成是多个独立的逻辑流。内部可以是多cpu并行,也可以是单cpu时间分片,能快速的切换逻辑流,看起来像是大家一块跑的就行。
    进程: 但是一块跑就有问题了。我计算到一半,刚把多次方程解到最后一步,你突然插进来,我的中间状态咋办,我用来储存的内存被你覆盖了咋办?所以跑在一个cpu里面的并发都需要处理上下文切换的问题。进程就是这样抽象出来个一个概念,搭配虚拟内存、进程表之类的东西,用来管理独立的程序运行、切换。
    并行: 后来一电脑上有了好几个cpu,好咧,大家都别闲着,一人跑一进程。就是所谓的并行。
    内核: 因为程序的使用涉及大量的计算机资源配置,把这活随意的交给用户程序,非常容易让整个系统分分钟被搞跪。所以核心的操作需要陷入内核(kernel),切换到操作系统,让老大帮你来做。
    线程: 有的时候碰着I/O访问,阻塞了后面所有的计算。空着也是空着,老大就直接把CPU切换到其他进程,让人家先用着。当然除了I\O阻塞,还有时钟阻塞等等。一开始大家都这样弄,后来发现不成,太慢了。为啥呀,一切换进程得反复进入内核,置换掉一大堆状态。进程数一高,大部分系统资源就被进程切换给吃掉了。后来搞出线程的概念,大致意思就是,这个地方阻塞了,但我还有其他地方的逻辑流可以计算,这些逻辑流是共享一个地址空间的,不用特别麻烦的切换页表、刷新TLB,只要把寄存器刷新一遍就行,能比切换进程开销少点。
    行,故事讲到这里,我们来看看并发的好处:
    该干嘛干嘛,多逻辑流先天符合人类描述问题的习惯;
    对于I/O密集的应用,被I/O阻塞的时候能切换到计算中去,可以显著的提升程序的响应速度。
    我们看到阻塞、切换到其他进程(线程)的操作,都会交由操作系统来完成。所以不管是进程还是线程,每次阻塞、切换都需要陷入系统调用(system call),先让CPU跑操作系统的调度程序,然后再由调度程序决定该跑哪一个进程(线程)。
    协程:如果我们不要这些功能了,我自己在进程里面写一个逻辑流调度的东西,碰着i\o我就用非阻塞式的。那么我们即可以利用到并发优势,又可以避免反复系统调用,还有进程切换造成的开销,分分钟给你上几千个逻辑流不费力。这就是协程。
    注:本质上协程就是用户空间下的线程。
    5.函数与协程
    http://www.zhihu.com/question/20511233
    线程是很丑陋的东西,线程不过是反映了当前硬件技术的物理限制瓶颈,线程不过是个妥协的产物
    单个cpu的计算能力不足,所以要多核。内存的容量太小太昂贵,所以需要硬盘
    协程反映了程序逻辑的一种需求:可重入能力
    函数,重入函数,过程
    函数中局部变量的值 = 过程中的局部状态
    希望有这么一种过程,每次进入,过程里的局部状态,都能保留上一次进入的状态————协程
    普通过程(函数)可看成这个特殊过程的一个特例:只有一个状态,每次进入时局部状态重置
    没有函数之前,你只有表达式,没有表达式之前,你只有mov。没有if-else之前,你只有jump
    脱离低级的逻辑处理,就意味着能在更高的抽象层面看问题
    协程不过是一个逻辑控制需求。一些语言原生支持,不支持也可以用原有的材料构建出来
    协程的实现,无非是你要维护一组局部状态,在重新进入协程前,保证这些状态不被改变,你能顺利定位到之前的位置
    你平时所写的一些逻辑控制代码,经典如状态机或对象等,也许就已经是一种“协程”了
    协程的最大的好处是在写过程式(命令式)风格的代码时,很好的简化了逻辑的流程
    6.角色模型
    每个角色是独立的单元,不会共享数据
    角色之间通过邮箱(类似email)来通信
    没有锁和同步块
    角色模型使并发更简单
    Erlang和Scala的并发模型就是基于角色,而不是线程
    角色模型没有移植到java平台里
    由于JVM对替代语言的开放性,java平台可以使用Groovy(角色库 GPars)或Scala来利用角色
    Kilim: 支持角色模型且基于Java的库
    7.Kilim
    角色: 使用 Task类型来表示
    Task: 是轻量型的线程,通过Mailbox与其他Task通信
    Kilim实现浅析(一)
    http://www.blogjava.net/killme2008/archive/2010/09/17/332281.html
    8.性能评比
    http://www.open-open.com/doc/view/c9b06f9f088741c3b7138f748d09268b

     

    *
    并发编程
    Java 开发 2.0: Kilim 简介
    http://www.ibm.com/developerworks/cn/java/j-javadev2-7.html
    如今已有许多并发模型,一种特别有趣并获得了 Java 社区认可的模型就是角色模型
    角色模型
    是一种不同的并发进程建模方式,与通过共享内存与锁交互的线程不同,角色模型利用了 “角色” 概念,使用邮箱来传递异步消息
    角色: 独立且完全不同的实体,不会共享内存来进行通信,仅能通过邮箱通信
    没有锁和同步块,所以不会出现由它们引发的问题(比如死锁、严重的丢失更新问题)
    角色能够并发工作,而不是采用某种顺序方式,角色模型本身能够处理协调问题
    使并发编程更加简单了
    它已经存在很长时间了
    一些语言(比如 Erlang 和 Scala)的并发模型就是基于角色的,而不是基于线程
    即语言层面提供的yield和resume原语,用来切换过程的逻辑流处理
    角色模型并没有植入到 Java 平台中
    Kilim
    Task: 角色(轻量型的线程)
    Mailbox: 邮箱(角色间的通信工具)
    使创建并发进程变得轻松而简单:只需从 Kilim 的 Task 类型进行扩展并实现 execute 方法
    Task 的 execute 方法抛出 Pausable,execute 的操作将在 Kilim 的调度程序控制下进行(即:Kilim 将确保 execute 以一种安全的方式并行地运行)
    Task.sleep(1000): 由Kilim托管的轻量型线程,进入休眠状态
    Mailbox.putnb(): 非阻塞
    Mailbox.get(): 阻塞
    weaver: 转换类的字节码的进程
    一个简单的后处理过程,在编译了类之后运行它
    把一些特殊代码添加到包含 Pausable 标记的各种类和方法中
    ant调用weaver
    <target name="weave" depends="compile" description="handles Kilim byte code weaving">
    <java classname="kilim.tools.Weaver" fork="yes">
    <classpath refid="classpath" />
    <arg value="-d" />
    <arg value="./target/classes" />
    <arg line="./target/classes" />
    </java>
    </target>
    影响java nio框架性能的因数(kilim作者的分析)
    http://blog.sina.com.cn/s/blog_56c9b55c0100vrts.html
    问题
    为了处理很多socket连接和优化吞吐量,会导致了大量的线程切换
    有很多次的selector的中断和调用,唤醒seletor是很费资源的操作
    优化
    对read writer process操作分别作轻量级的scheduler,基于actor
    有个trick,就是read或者write操作时候,但没有读满或者写完的情况下,并不是 立即返回并再次注册channel到selector,而是再尝试若干次(3次),再返回并注册到 selector。
    在Java中使用协程(Coroutine)
    http://www.blogjava.net/BlueDavy/archive/2010/01/28/311148.html
    采用Coroutine方式可以很好的绕开需要启动太多线程来支撑高并发出现的瓶颈,提高Java应用所能支撑的并发量


    *
    高并发(高性能)web

    网站Web性能测试:ApacheBench,Webbench,http_load使用教程
    http://yusi123.com/2950.html
    nginx优化 实现10万并发访问量
    http://www.cnblogs.com/pricks/p/3837149.html

    最大连接数: 指服务器能够响应http请求的个数,不会出现无响应的页面(目前使用nginx,每个线程能支持10w的连接)(传统的以线程来响应请求的服务器很容易因为连接数太多而挂掉)
    最大并发数: 指同一时刻(瞬间)向服务器发出http请求的个数(但是并不一定能在1秒内都返回结果,或者响应请求,一般由服务器的最大连接数决定)
    最大响应数: 服务器一定时间内返回http请求的个数(通常需要观察服务器一段时间,统计出返回的http总数,然后得出以秒为单位的结果,即:QPS)
    最大峰值数: 指线上服务器运营时,实际碰到的最大并发数(高峰时段,如团购网站)(saa最大为30左右)

    单个请求速度: 单个请求最快返回用时(saa的rpc服务端每个请求在10ms以内)
    cpu占用率: 传统的以线程来响应http请求的服务器,可能因为线程切换平凡而导致cpu占用率过高
    内存占用率: 同cpu

    nginx可以做负载均衡,分配httq请求给多个resin去处理
    反向代理服务器,而且nginx还可以按照调度规则实现动态、静态页面的分离,可以按照轮询、ip哈希、URL哈希、权重等多种方式对后端服务器做负载均衡
    多台resin是为了提高web服务的最大响应数(QPS),即:尽快处理完用户的请求(相当于电脑用多个cpu提高计算速度)
    不管是nginx还是resin,都可以使用nio来降低线程数(nio不会阻塞线程,因此可以只使用少量线程),从而减少对cpu和内存的消耗
    队列: 用来保存http请求(让http有序,并降低冲击到底层可接受的范围(一条处理完再处理下一条,例如不同时读写表让mysql死锁))
    httpsqs: 基于 HTTP GET/POST 协议的轻量级开源简单消息队列服务
    rabbitmq: 支持对消息的可靠的传递,支持事务,不支持批量的操作
    kafka: 具有高的吞吐量;支持主备模式;采用zookeeper对集群中的broker、consumer进行管理,可以注册topic到zookeeper上;通过zookeeper的协调机制,producer保存对应topic的broker信息,可以随机或者轮询发送到broker上;并且producer可以基于语义指定分片,消息发送到broker的某分片上
    rpc服务: 使得系统能把多个硬件的性能集合起来使用,多核或多个cpu,多机内存,提高最大响应数(QPS)。而且提高系统稳定性,不会出现单点故障问题。


    Advanced Message Queuing Protocol (AMQP)
    Exchange 和 Queue

    producer,broker,consumer

    常见开源消息系统
    http://blog.jobbole.com/45547/
    消息系统的作用:异步处理、削减峰值、减少组件之间的耦合

    分布式系统
    并行和高性能应用
    容错应用