精华内容
下载资源
问答
  • 并行编程模式pdf
    2021-05-20 16:06:04

    MPI并行编程入门

    中国科学院计算机网络信息中心

    超级计算中心

    参考材料

    张林波 清华大学出版社 莫则尧 科学出版社 都志辉 清华大学出版社

    消息传递平台MPI

    • 什么是MPI (Message Passing Interface )

    – 是函数库规范,而不是并行语言;操作如同库函数调用

    – 是一种标准和规范,而非某个对它的具体实现(MPICH等),

    与编程语言无关

    – 是一种消息传递编程模型,并成为这类编程模型的代表

    • What is the message?

    DATA+ENVELOPE

    • MPI的目标

    – 较高的通信性能

    – 较好的程序可移植性

    – 强大的功能

    消息传递平台MPI

    • MPI的产生

    – 1992-1994年,MPI 1.1版本问世

    – 1995-1997年,MPI 2.0版本出现

    • 扩充并行I/O

    • 远程存储访问

    • 动态进程管理等

    • MPI的语言绑定

    – Fortran (科学与工程计算)

    – C (系统和应用程序开发)

    • 主要的MPI实现

    – 并行机厂商提供

    – 高校、科研部门

    • MPICH (/mpi/mpich )

    • LAMMPI (/)

    消息传递平台MPI

    • MPI程序编译与运行

    – 程序编译

    C: %mpicc -o mpiprog mpisrc.c

    Fortran 77: %mpif77 -o mpiprog mpisrc.f

    – 程序运行

    %mpirun -np 4 mpiprog

    •程序执行过程中不能动态改变进程的个数

    •申请的进程数np与实际处理器个数无关

    MPI基础知识

    • 进程与消息传递

    • MPI重要概念

    • MPI函数一般形式

    • MPI原始数据类型

    • MPI程序基本结构

    • MPI几个基本函数

    • 并行编程模式

    进程与消息传递

    • 单个进程(process )

    – 进程与程序相联,程序一旦在操作系统中运行即成为进程。

    进程拥有独立的执行环境(内存、寄存器、程序计数器等)

    ,是操作系统中独立存在的可执行的基本程序单位

    – 串行应用程序编译形成的可执行代码,分为“指令”和“数据”两

    个部分,并在程序执行时“独立地申请和占有” 内存空间,且

    所有计算均局限于该内存空间。

    进程1 进程2

    内存

    进程与消息传递

    • 单机内多个进程

    – 多个进程可同时存在于单机内同一操作系统。操作系统负责

    调度分时共享处理机资源(CPU、内存、存储、外设等)

    – 进程间相互独立(内存空间不相交)。在操作系统调度下各

    自独立地运行,例如多个串行应用程序在同一台计算机运行

    – 进程间可以相互交换信息。例如数据交换、同步等待,消息

    是这些交换信息的基本单位,消息传递是指这些信息在进程

    间的相互交换,是实现进程间通信的唯一方式

    更多相关内容
  • 并行编程模式

    2018-06-26 05:14:00
    并行编程模式
  • 设计模式.net并行编程.pdf 设计模式.net并行编程.pdf 设计模式.net并行编程.pdf
  • 基于Linux并行编程模式的研究与实现.pdf
  • 云计算-云计算中的MapReduce并行编程模式研究.pdf
  • 云计算-面向云计算的MapReduce并行编程模式的研究与应用.pdf
  • 第2章主要介绍并行循环的知识,第3章介绍并行任务处理,第4章阐述并行合并计算的机理,第5章介绍future模式,第6章在前文的基础上深入探讨动态并行任务机制,第7章介绍并行编程的流水线机制。  《设计模式:NET并行...
  • 并行设计模式能够降低并行编程的难度与复杂度。针对科学与工程计算领域大量耗时的数据密集型应用的计算,提出了一种能够适用于阵列数据划分应用的FJRR并行设计模式;鉴于开发者更习惯串行编程,在FJRR模式中提出并...
  • 这本精品书籍浓墨重彩地描述如何使用C# 4、Visual Studio 2010和.NET Framework 4高效地创建基于任务的并行应用程序,详细讲述最新的单指令、多数据流指令和向量化等并行编程技术,介绍现代并行库,讨论如何珠联璧合...
  • 根据该模式数值计算的特点提出了一种并行求解三对角方程组的新方法,相对于传统算法编程简单而且并行效率更高;负载平衡是并行程序性能优化首先要解决的问题,以水格点的个数作为任务分解的标准,实现了较好的负载...
  • 利用并行计算中的OpenMP多核编程环境,采用曙光16核服务器为硬件平台,实现对动态模式识别算法的快速性;同时,以压气机Mansoux模型为应用背景,把确定学习理论的动态模式识别方法应用到压气机旋转失速/喘振的快速...
  • C#之:并行编程 - 1

    2019-08-31 20:11:53
    并行编程简介: 如果程序中有大量的计算任务,并且这些任务能分割成几个互相独立的任务块,那就应 该使用并行编程并行编程可临时提高CPU 利用率,以提高吞吐量,若客户端系统中的 CPU 经常处于空闲状态,这个方法...

    并行编程简介:

    如果程序中有大量的计算任务,并且这些任务能分割成几个互相独立的任务块,那就应
    该使用并行编程。并行编程可临时提高CPU 利用率,以提高吞吐量,若客户端系统中的
    CPU 经常处于空闲状态,这个方法就非常有用,但通常并不适合服务器系统。大多数服
    务器本身具有并行处理能力,例如ASP.NET 可并行地处理多个请求。某些情况下,在服
    务器系统中编写并行代码仍然有用(如果你知道并发用户数量会一直是少数)。但通常情
    况下,在服务器系统上进行并行编程,将降低本身的并行处理能力,并且不会有实际的
    好处。

    并行的两种形式:

    • 数据并行(data parallelism)。数据并行是指有大量的数据需要处理,并且每一块数据的处理过程基本上是彼此独立的。
    • 任务并行(task parallelim)。任务并行是指需要执行大量任务,并且每个任务的执行过程基本上是彼此独立的。任务并行可以是动态的,如果一个任务的执行结果会产生额外的任务,这些新增的任务也可以加入任务池。

    实现数据并行有几种不同的做法:

    1. 一种做法是使用Parallel.ForEach 方法,它类似于foreach 循环,应尽可能使用这种做法。
    2. 另一种做法是使用PLINQ(Parallel LINQ), 它为LINQ 查询提供了AsParallel 扩展。

    不管选用哪种方法,在并行处理时有一个非常重要的准则。每个任务块要尽可能的互相独立。
    只要任务块是互相独立的,并行性就能做到最大化。一旦你在多个线程中共享状态,就必
    须以同步方式访问这些状态,那样程序的并行性就变差了。

    任务并行:
    数据并行重点在处理数据,任务并行则关注执行任务。

    Parallel 类的Parallel.Invoke 方法可以执行“分叉/ 联合”(fork/join)方式的任务并行。现在Task 这个类也被用于异步编程,但当初它是为了任务并行而引入的。任务并行中使用的一个Task 实例表示一些任务。可以使用Wait 方法等待任务完成,还可以使用Result和Exception 属性来检查任务执行的结果。直接使用Task 类型的代码比使用Parallel 类要复杂,但是,如果在运行前不知道并行任务的结构,就需要使用Task 类型。如果使用动态并行机制,在开始处理时,任务块的个数是不确定的,只有继续执行后才能确定。通常情况下,一个动态任务块要启动它所需的所有子任务,然后等待这些子任务执行完毕。为实现这个功能,可以使用Task 类型中的一个特殊标志TaskCreationOptions.
    AttachedToParent。
    跟数据并行一样,任务并行也强调任务块的独立性。委托(delegate)的独立性越强,程序的执效率就越高。在编写任务并行程序时,要格外留意下闭包(closure)捕获的变量。记住闭包捕获的是引用(不是值),因此可以在结束时以不明显地方式地分享这些变量。

    任务不要特别短,也不要特别长 如果任务太短,把数据分割进任务和在线程池中调度任务的开销会很大。如果任务太长,线程池就不能进行有效的动态调整以达到工作量的平衡

    Parallel 类:

    Parallel 类是对线程的一个很好抽象。该类位于:System.Threading.Tasks 命名空间中,提供了数据和任务的并行性。
    Parallel 类定义了并行的 for 和 foreach 的静态方法。对于C# 中 for 和 foreach 语句而言,循环从一个线程中运行。Parallel 使用多个任务,因此使用多个线程来完成这个作业。

    官方链接:Parallel

    Parallel.For()方法:

    主要是针对处理数组元素的并行操作。

    Dome1
    第一个参数是开始索引(含)。第二个参数是结束索引(不含)。第三个参数是 Action委托。整型参数是循环的迭代次数,该参数被传递给委托引用的方法。

     static void Main(string[] args)
            {
                int[] nums = { 1, 2, 3, 4, 5 };
                Parallel.For(0, nums.Length, (i) => {
                    Console.WriteLine("针对数组索引 {0} 对应元素{1} 的一些工作代码... ...",i,nums[i]);
                });
    
                Console.ReadKey();
            }
    

    输出:
    在这里插入图片描述
    可以看到,工作代码并没有按照数组的索引次序进行遍历。这是因为我们遍历是并行的,不是顺序的。所以,如果我们输出必须是同步的或者必须是顺序输出的,则不应使用Parallel的方式。

    Dome2:
    Parallel.For()方法的返回类型是 ParallelLoopResult 结构体,它提供了循环是否结束的信息。

     static void Main(string[] args)
            {
                ParallelLoopResult result = Parallel.For(0, 10, i =>
                {
                    Console.WriteLine("序号:{0},任务:{1},线程:{2}",i,Task.CurrentId,Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(10);
                });
    
                Console.WriteLine("是否完成所有任务:{0}",result.IsCompleted);
    
                Console.ReadKey();
            }
    

    输出:
    在这里插入图片描述
    从输出可以看出,有5个任务和5个线程。任务不一定映射到一个线程上,线程也可以被不同的任务重用。

    Dome3,异步等待:
    Task.Delay(); 是一个异步延迟等待方法,用于释放线程提供其他任务使用。下面的代码使用 await 关键字,所以一旦完成延迟,就立即开始调用这些代码。延迟后执行的代码和延迟前执行的代码可以运行在不同的线程中。

          static void Main(string[] args)
            {
                //async:异步方法前加关键字
                ParallelLoopResult result = Parallel.For(0, 10, async i =>
                {
                    Console.WriteLine("序号:{0},任务:{1},线程:{2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
                    await  Task.Delay(10);
                    Console.WriteLine("序号:{0},任务:{1},线程:{2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
                });
    
                Console.WriteLine("是否完成所有任务:{0}", result.IsCompleted);
    
                Console.ReadKey();
            }
    

    输出:
    在这里插入图片描述
    从输出结果可以看出,调用 Task.Delay() 方法后,线程发生了变化。例如:在循环迭代序号2 在延迟前线程ID是 4,在延迟后线程ID是9。还可以看到任务不存在,只留下线程了。而且这里重用了前面的线程。
    另一个重要方面是,Parallel类的 for 方法并没有等待延迟,而是直接完成。Parallel 类只等待他创建的任务,而不等待其他后台活动。在延迟后,也有可能完全看不到方法的输出。出现这种情况的原因是主线程(前台线程)结束。所有的后台线程被终止。

    提前停止Parallel.For :
    可以提前中断 Parallel.For 方法,而不是完成所有迭代。 For()方法的一个重载版本接受第三个 Action<int, ParallelLoopState> 类型的参数。使用这些参数定义一个方法,就可以调用 ParallelLoopState 的 Break() 或 Stop()方法,以影响循环结果。

    static void Main(string[] args)
            {
                //async:异步方法前加关键字
                ParallelLoopResult result = Parallel.For(10, 40, async (int i,ParallelLoopState pls) =>
                {
                    Console.WriteLine("序号:{0},任务:{1},线程:{2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
                    await Task.Delay(10);
                    if(i>15)
                    {
                        pls.Break();
                    }
                });
    
                Console.WriteLine("是否完成所有任务:{0}", result.IsCompleted);
                Console.WriteLine("最后结束迭代索引:{0}",result.LowestBreakIteration);
                Console.ReadKey();
            }
    

    输出:
    在这里插入图片描述
    输出运行说明:迭代 在值大于15时中断,但其他任务可以同时运行,有其他值的任务也可以运行。利用 LowestBreakIteration 属性,可以忽略其他任务结果。

    Break():告知 System.Threading.Tasks.Parallel 循环应在系统方便的时候尽早停止执行当前迭代之外的迭代。
    Stop():告知 System.Threading.Tasks.Parallel 循环应在系统方便的时候尽早停止执行。

    使用Break()方法每次停止迭代的索引都不相同。因为这是有系统决定的。

    Parallel.For()的重载Dome:

    Parallel.For() 方法可以使用几个线程来执行循环,如果需要对每个线程进行初始化,就可以使用 P a r a l l e l . F o r &lt; T L o c a l &gt; ( ) Parallel.For&lt;TLocal&gt;() Parallel.For<TLocal>() 方法。除了 form 和 to 对应的值之外,For方法的泛型版本还接受3个委托参数。
    第一个参数类型是: F u n c &lt; T L o c a l &gt; Func &lt;TLocal&gt; Func<TLocal> ,下面例子对TLocal使用字符串,所以该方法需要定义为 F u n c &lt; S t r i n g &gt; Func&lt;String&gt; Func<String> , 即返回string 的方法。这个方法仅对于执行迭代的每个线程调用一次。

    第二个参数为循环体定义了委托。在示例中,该参数的类型是 F u n c &lt; i n t , P a r a l l e l L o o p S t a t e , s t r i n g , s t r i n g &gt; Func&lt;int,ParallelLoopState,string,string&gt; Func<int,ParallelLoopState,string,string> 。其中,第一个参数是循环迭代,第二个参数是允许停止循环。循环体方法通过第三个参数接受从 inint 方法返回的值,循环体方法还需要返回一个值,其类型用于泛型For方法的参数定义。

    For()方法的最后一个参数指定一个委托 A c t i o n &lt; T L o c a l &gt; Action&lt;TLocal&gt; Action<TLocal>,在下例中,接受一个字符串。这个方法对于每个线程调用一次,这是一个线程退出的方法。

     static void Main(string[] args)
            {
                Parallel.For<string>(0, 20, () => {
                    //为每个线程调用一次,必须有返回值
                    Console.WriteLine("初始化 线程:{0};任务:{1}",Thread.CurrentThread.ManagedThreadId,Task.CurrentId);
                    return string.Format("Thread{0}", Thread.CurrentThread.ManagedThreadId);
                }, (i, pls, str1) => {
                    //每个数字调用一次,必须有返回值
                    Console.WriteLine("body i {0}; str1 {1}; thread {2}; task {3}",i,str1,Thread.CurrentThread.ManagedThreadId,Task.CurrentId);
                    Thread.Sleep(10);
                    return string.Format("i {0}", i);
                }, (str1) => {
                    //对每个线程的最后操作
                    Console.WriteLine("最后:{0}",str1);
                });
    
    
                Console.ReadKey();
            }
    

    输出:
    在这里插入图片描述

    Parallel.ForEach()方法:

    Parallel.ForEach()方法 遍历实现了IEnumerable 的集合,其方式 类似于 foreach 语句,但以异步方式遍历。这里也没有确定遍历顺序。

    Dome1:

     static void Main(string[] args)
            {
                string[] data = { "A", "B", "C", "D", "E", "F", "G", "J", "K", "L", "M", "N" };
                ParallelLoopResult result = Parallel.ForEach<string>(data, s =>
                {
                    Console.WriteLine(s);
                });
                Console.ReadKey();
            }
    

    输出:
    在这里插入图片描述
    如果需要中断循环,就可以使用 ForEach()方法的重载版本和 ParallelLoopState参数。其方式与前面的For()方法相同。Foreach()方法的一个重载版本也可以用于索引器,从而获得迭代次数。

     static void Main(string[] args)
            {
                string[] data = { "A", "B", "C", "D", "E", "F", "G", "J", "K", "L", "M", "N" };
                ParallelLoopResult result = Parallel.ForEach<string>(data, (s,pls,i)=>
                {
                    Console.WriteLine("{0},序号:{1}",s,i);
                });
                Console.ReadKey();
            }
    

    输出:
    在这里插入图片描述
    Dome2:实例运用:

         static void Main(string[] args)
            {
                List<int> ls1 = new List<int>() { 1, 1, 1, 1, 1, 1 };
                List<int> ls2 = new List<int>() { 2, 2, 2, 2, 2, 2 };
                Function(new List<List<int>>() { ls1, ls2 }, 2);
    
                foreach (var item in ls1)
                {
                    Console.Write(item+",");
                }
                Console.WriteLine();
                foreach (var item in ls2)
                {
                    Console.Write(item + ",");
                }
    
                Console.ReadKey();
            }
    
            static void Function(IEnumerable<List<int>> listNum, int n)
            {
                Parallel.ForEach(listNum, list =>
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        list[i] *= n;
                    }
                });
            }
    

    输出:
    在这里插入图片描述

    下面的例子使用了一批矩阵,对每一个矩阵都进行旋转:

    void RotateMatrices(IEnumerable<Matrix> matrices, float degrees)
    {
        Parallel.ForEach(matrices, matrix => matrix.Rotate(degrees));
    }
    

    在某些情况下需要尽早结束这个循环,例如发现了无效值时。下面的例子反转每一个矩
    阵,但是如果发现有无效的矩阵,则中断循环:

     void InvertMatrices(IEnumerable<Matrix> matrices)
            {
                Parallel.ForEach(matrices, (matrix, state) =>
                {
                    if (!matrix.IsInvertible)
                        state.Stop();
                    else
                        matrix.Invert();
                });
            }
    

    更常见的情况是可以取消并行循环,这与结束循环不同。结束(stop)循环是在循环内部
    进行的,而取消(cancel)循环是在循环外部进行的。例如,点击“取消”按钮可以取消
    一个CancellationTokenSource,以取消并行循环,方法如下:

           void RotateMatrices(IEnumerable<Matrix> matrices, float degrees,CancellationToken token)
            {
                Parallel.ForEach(matrices,new ParallelOptions { CancellationToken = token }, matrix => matrix.Rotate(degrees));
            }
    

    Parallel的注意点:

    在 Parallel for 或 Foreach 方法的一些复杂方法应用中。我们可以在每个任务启动时执行初始化操作,在每个任务结束后,又执行一些后续工作,同时,还允许我们监视线程的状态。

    如下:

     		static void Main(string[] args)
            {
                int[] nums = new int[] { 1, 2, 3, 4 };
                int total = 0;
                Parallel.For<int>(0, nums.Length, () =>
                {
                    return 1;
                }, (i, state, subTotal) =>
                {
                    subTotal += nums[i];
                    return subTotal;
                },x=> {
                    Interlocked.Add(ref total, x);
                });
                Console.WriteLine("total={0}",total);     
                Console.ReadKey();
            }
    

    这段代码有可能输出11,也许时12,理论上输出13或14。为什么会这样输出,首先来了解一下For方法的各个参数:

     public static ParallelLoopResult For<TLocal>(int fromInclusive, int toExclusive, Func<TLocal> localInit, Func<int, ParallelLoopState, TLocal, TLocal> body, Action<TLocal> localFinally);
    

    前面两个参数时:fromInclusive(起始索引) 和 toExclusive(结束索引)。
    参数:body;即任务的本身,其中 subTotal 是单位个任务的返回值。
    localInitlocalFinally 比较难以理解。要理解这两个参数,首先要理解 Parallel.For 方法的运作模式。For 是采用并发的方式来启动循环体中的每个任务,这意味着,任务是交给线程池管理的。在上面的代码中循环次数共计 4 次,实际允许时调度的后台线程也许就只有一个或两个。这是并发的优势,也是线程池的优势,Parallel 通过内部的算法,最大的节约了线程的消耗。localInit的作用是 ,如果Parallel 为我们新起了一个线程时,它就会执行一些初始化的任务。在上面的例子中:

    			() =>
                {
                    return 1;
                },
    

    他会将任务体中的 subTotal 这个值初始化为 1。

    localFinally 的作用是,在每个线程结束时,它执行一些收尾工作:

     Interlocked.Add(ref total,  x);
    

    这行代码所代表的收尾工作就是:

    total = total+ subTotal ;
    

    其中的 x ,其实代表的就是任务体中的返回值,具体在这个例子中就是 subTotal 在返回时的值。使用 Interlocked 对 total 进行原子操作,以避免并发带来的问题。
    现在,应该很好理解上面的例子输出不确定了。 Parallel 一共启动了4个任务,但不能确定 Parallel 启动了多少个线程,那是运行时根据自己的算法决定的。如果所有的并发任务只用了一个线程,则输出为 11 ; 如果用来两个线程,那么根据程序逻辑来看,输出就是12。
    在这段代码中,如果让 localInit 的返回值为 0 也许就永远不会注意到这个问题。

    		() =>
                {
                    return 0;
                },
    

    下一章继续… …

    展开全文
  • 本书介绍了如何通过Intel线程构建模块来最大限度地...书中包含了大量的示例和丰富的资料,给出了常见的使用模式,揭示了TBB中的精彩之处,并且还提供了一些指导意见,来在不同的并行编程方式上进行选择以获得最佳的性能
  • Java并发编程实战 PDF

    2021-02-12 13:21:36
    3.5.3 安全发布的常用模式 3.5.4 事实不可变对象 3.5.5 可变对象 3.5.6 安全地共享对象 第4章 对象的组合 4.1 设计线程安全的类 4.1.1 收集同步需求 4.1.2 依赖状态的操作 4.1.3 状态的所有权 4.2 实例...

    目录

    对本书的赞誉

    译者序

    前 言

    第1章 简介

    1.1 并发简史

    1.2 线程的优势

    1.2.1 发挥多处理器的强大能力

    1.2.2 建模的简单性

    1.2.3 异步事件的简化处理

    1.2.4 响应更灵敏的用户界面

    1.3 线程带来的风险

    1.3.1 安全性问题

    1.3.2 活跃性问题

    1.3.3 性能问题

    1.4 线程无处不在

    第一部分 基础知识

    第2章 线程安全性

    2.1 什么是线程安全性

    2.2 原子性

    2.2.1 竞态条件

    2.2.2 示例:延迟初始化中的竞态条件

    2.2.3 复合操作

    2.3 加锁机制

    2.3.1 内置锁

    2.3.2 重入

    2.4 用锁来保护状态

    2.5 活跃性与性能

    第3章 对象的共享

    3.1 可见性

    3.1.1 失效数据

    3.1.2 非原子的64位操作

    3.1.3 加锁与可见性

    3.1.4 Volatile变量

    3.2 发布与逸出

    3.3 线程封闭

    3.3.1 Ad-hoc线程封闭

    3.3.2 栈封闭

    3.3.3 ThreadLocal类

    3.4 不变性

    3.4.1 Final域

    3.4.2 示例:使用Volatile类型来发布不可变对象

    3.5 安全发布

    3.5.1 不正确的发布:正确的对象被破坏

    3.5.2  不可变对象与初始化安全性

    3.5.3 安全发布的常用模式

    3.5.4 事实不可变对象

    3.5.5 可变对象

    3.5.6 安全地共享对象

    第4章 对象的组合

    4.1 设计线程安全的类

    4.1.1 收集同步需求

    4.1.2 依赖状态的操作

    4.1.3 状态的所有权

    4.2 实例封闭

    4.2.1 Java监视器模式

    4.2.2 示例:车辆追踪

    4.3 线程安全性的委托

    4.3.1 示例:基于委托的车辆追踪器

    4.3.2 独立的状态变量

    4.3.3 当委托失效时

    4.3.4 发布底层的状态变量

    4.3.5 示例:发布状态的车辆追踪器

    4.4 在现有的线程安全类中添加功能

    4.4.1 客户端加锁机制

    4.4.2 组合

    4.5 将同步策略文档化

    第5章 基础构建模块

    5.1 同步容器类

    5.1.1 同步容器类的问题

    5.1.2 迭代器与Concurrent-ModificationException

    5.1.3 隐藏迭代器

    5.2 并发容器

    5.2.1 ConcurrentHashMap

    5.2.2 额外的原子Map操作

    5.2.3 CopyOnWriteArrayList

    5.3 阻塞队列和生产者-消费者模式

    5.3.1 示例:桌面搜索

    5.3.2 串行线程封闭

    5.3.3 双端队列与工作密取

    5.4 阻塞方法与中断方法

    5.5 同步工具类

    5.5.1 闭锁

    5.5.2 FutureTask

    5.5.3 信号量

    5.5.4 栅栏

    5.6 构建高效且可伸缩的结果缓存

    第二部分 结构化并发应用程序

    第6章 任务执行

    6.1 在线程中执行任务

    6.1.1 串行地执行任务

    6.1.2 显式地为任务创建线程

    6.1.3 无限制创建线程的不足

    6.2 Executor框架

    6.2.1 示例:基于Executor的Web服务器

    6.2.2 执行策略

    6.2.3 线程池

    6.2.4 Executor的生命周期

    6.2.5 延迟任务与周期任务

    6.3 找出可利用的并行性

    6.3.1 示例:串行的页面渲染器

    6.3.2 携带结果的任务Callable与Future

    6.3.3 示例:使用Future实现页面渲染器

    6.3.4 在异构任务并行化中存在的局限

    6.3.5 CompletionService:Executor与BlockingQueue

    6.3.6 示例:使用CompletionService实现页面渲染器

    6.3.7 为任务设置时限

    6.3.8 示例:旅行预定门户网站

    第7章 取消与关闭

    7.1 任务取消

    7.1.1 中断

    7.1.2 中断策略

    7.1.3 响应中断

    7.1.4 示例:计时运行

    7.1.5 通过Future来实现取消

    7.1.6 处理不可中断的阻塞

    7.1.7 采用newTaskFor来封装非标准的取消

    7.2 停止基于线程的服务

    7.2.1 示例:日志服务

    7.2.2 关闭ExecutorService

    7.2.3 “毒丸”对象

    7.2.4 示例:只执行一次的服务

    7.2.5 shutdownNow的局限性

    7.3 处理非正常的线程终止

    7.4 JVM关闭

    7.4.1 关闭钩子

    7.4.2 守护线程

    7.4.3 终结器

    第8章 线程池的使用

    8.1 在任务与执行策略之间的隐性耦合

    8.1.1 线程饥饿死锁

    8.1.2 运行时间较长的任务

    8.2 设置线程池的大小

    8.3 配置ThreadPoolExecutor

    8.3.1 线程的创建与销毁

    8.3.2 管理队列任务

    8.3.3 饱和策略

    8.3.4 线程工厂

    8.3.5 在调用构造函数后再定制ThreadPoolExecutor

    8.4 扩展 ThreadPoolExecutor

    8.5 递归算法的并行化

    第9章 图形用户界面应用程序

    9.1 为什么GUI是单线程的

    9.1.1 串行事件处理

    9.1.2 Swing中的线程封闭机制

    9.2 短时间的GUI任务

    9.3 长时间的GUI任务

    9.3.1 取消

    9.3.2 进度标识和完成标识

    9.3.3 SwingWorker

    9.4 共享数据模型

    9.4.1 线程安全的数据模型

    9.4.2 分解数据模型

    9.5 其他形式的单线程子系统

    第三部分 活跃性、性能与测试

    第10章 避免活跃性危险

    10.1 死锁

    10.1.1 锁顺序死锁

    10.1.2 动态的锁顺序死锁

    10.1.3 在协作对象之间发生的死锁

    10.1.4 开放调用

    10.1.5 资源死锁

    10.2 死锁的避免与诊断

    10.2.1 支持定时的锁

    10.2.2 通过线程转储信息来分析死锁

    10.3 其他活跃性危险

    10.3.1 饥饿

    10.3.2 糟糕的响应性

    10.3.3 活锁

    第11章 性能与可伸缩性

    11.1 对性能的思考

    11.1.1 性能与可伸缩性

    11.1.2 评估各种性能权衡因素

    11.2 Amdahl定律

    11.2.1 示例:在各种框架中隐藏的串行部分

    11.2.2 Amdahl定律的应用

    11.3 线程引入的开销

    11.3.1 上下文切换

    11.3.2 内存同步

    11.3.3 阻塞

    11.4 减少锁的竞争

    11.4.1 缩小锁的范围(“快进快出”)

    11.4.2 减小锁的粒度

    11.4.3 锁分段

    11.4.4 避免热点域

    11.4.5 一些替代独占锁的方法

    11.4.6 监测CPU的利用率

    11.4.7 向对象池说“不”

    11.5 示例:比较Map的性能

    11.6 减少上下文切换的开销

    第12章 并发程序的测试

    12.1 正确性测试

    12.1.1 基本的单元测试

    12.1.2 对阻塞操作的测试

    12.1.3 安全性测试

    12.1.4 资源管理的测试

    12.1.5 使用回调

    12.1.6 产生更多的交替操作

    12.2 性能测试

    12.2.1 在PutTakeTest中增加计时功能

    12.2.2 多种算法的比较

    12.2.3 响应性衡量

    12.3 避免性能测试的陷阱

    12.3.1 垃圾回收

    12.3.2 动态编译

    12.3.3 对代码路径的不真实采样

    12.3.4 不真实的竞争程度

    12.3.5 无用代码的消除

    12.4 其他的测试方法

    12.4.1 代码审查

    12.4.2 静态分析工具

    12.4.3 面向方面的测试技术

    12.4.4 分析与监测工具

    第四部分 高级主题

    第13章 显式锁

    13.1 Lock与 ReentrantLock

    13.1.1 轮询锁与定时锁

    13.1.2 可中断的锁获取操作

    13.1.3 非块结构的加锁

    13.2 性能考虑因素

    13.3 公平性

    13.4 在synchronized和ReentrantLock之间进行选择

    13.5 读-写锁

    第14章 构建自定义的同步工具

    14.1 状态依赖性的管理

    14.1.1 示例:将前提条件的失败传递给调用者

    14.1.2 示例:通过轮询与休眠来实现简单的阻塞

    14.1.3 条件队列

    14.2 使用条件队列

    14.2.1 条件谓词

    14.2.2 过早唤醒

    14.2.3 丢失的信号

    14.2.4 通知

    14.2.5 示例:阀门类

    14.2.6 子类的安全问题

    14.2.7 封装条件队列

    14.2.8 入口协议与出口协议

    14.3 显式的Condition对象

    14.4 Synchronizer剖析

    14.5 AbstractQueuedSynchronizer

    14.6 java.util.concurrent同步器类中的 AQS

    14.6.1 ReentrantLock

    14.6.2 Semaphore与CountDownLatch

    14.6.3 FutureTask

    14.6.4 ReentrantReadWriteLock

    第15章 原子变量与非阻塞同步机制

    15.1 锁的劣势

    15.2 硬件对并发的支持

    15.2.1 比较并交换

    15.2.2 非阻塞的计数器

    15.2.3 JVM对CAS的支持

    15.3 原子变量类

    15.3.1 原子变量是一种“更好的volatile”

    15.3.2 性能比较:锁与原子变量

    15.4 非阻塞算法

    15.4.1 非阻塞的栈

    15.4.2 非阻塞的链表

    15.4.3 原子的域更新器

    15.4.4 ABA问题

    第16章 Java内存模型

    16.1 什么是内存模型,为什么需要它

    16.1.1 平台的内存模型

    16.1.2 重排序

    16.1.3 Java内存模型简介

    16.1.4 借助同步

    16.2 发布

    16.2.1 不安全的发布

    16.2.2 安全的发布

    16.2.3 安全初始化模式

    16.2.4 双重检查加锁

    16.3 初始化过程中的安全性

    附录A 并发性标注

    参考文献

    展开全文
  • 并行计算导论系统介绍涉及并行计算的体系结构、编程范例、算法与应用和标准等。覆盖了并行计算领域的传统问题,并且尽可能地采用与底层平台无关的体系结构和针对抽象模型来设计算法。书中选择MPI(Message Passing ...

    并行计算导论系统介绍涉及并行计算的体系结构、编程范例、算法与应用和标准等。覆盖了并行计算领域的传统问题,并且尽可能地采用与底层平台无关的体系结构和针对抽象模型来设计算法。书中选择MPI(Message Passing Interface)、POSIX线程和OpenMP这三个应用*广泛的编写可移植并行程序的标准作为编程模型,并在不同例子中反映了并行计算的不断变化的应用组合。本书结构合理,可读性强,加之每章精心设计的习题集,更加适合教学。 本书论述清晰,示例生动,并附有大量习题,适合作为高等院校计算机及相关专业本科生和研究生的教材或参考书。原版自1993年出版第1版到2003年出版第2版以来,已在世界范围内被广泛地采用为高等院校本科生和研究生的教材或参考书。

    aef9653fbefb526c7cc0a091ea12c163.png

    内容简介

    本书全面介绍并行计算的各个方面,包括体系结构、编程范例、算法与应用和标准等,涉及并行计算的新技术,也覆盖了较传统的算法,如排序、搜索、图和动态编程等。本书尽可能采用与底层平台无关的体系结构并且针对抽象模型来设计处落地。书中选择MPI、POSIX线程和OpenMP作为编程模型,并在不同例子中反映了并行计算的不断变化的应用组合。

    本书论述清晰,示例生动。并附有大量习题。适合作为高等院校计算机及相关专业本科生和研究生的教材或参考书。

    作者简介

    Ananth Grama 普度大学计算机科学系的副教授,研究领域是并行和分布式系统和应用的不同方面。Anshul Gupta IBM T.3J.3Watson Research Center的研究人员,研究领域是并行算法和科学计算。George Karypis 明尼苏达大学计算机科学和工程系的副教授,研究领域是并行算法设计.数据挖掘和生物信息学等。Vipin Kumar 明尼苏达大学计算机科学与工程系的教授,美国军用高性能计算研究中心的主任,研究领域是高性能计算. 用于科学计算问题和数据挖掘的并行算法

    目录

    第1章  并行计算介绍

    1. 1  推动并行化

    1. 1. 1  计算能力因素--从晶体管到

    浮点运算速度

    1. 1. 2  内存及磁盘速度的因素

    1. 1. 3  数据通信因素

    1. 2  并行计算适用范围

    1. 2. 1  在工程及设计中的应用

    1. 2. 2  科学计算中的应用

    1. 2. 3  商业应用

    1. 2. 4  计算机系统中的应用

    1. 3  本书的组织及内容

    1. 4  书目评注

    习题

    第2章  并行编程平台

    2. 1  隐式并行:微处理器体系结构的

    发展趋势*

    2. 1. 1  流水线与超标量执行

    2. 1. 2  超长指令字处理器

    2. 2  内存系统性能的局限*

    2. 2. 1  使用高速缓存改善有效内存延迟

    2. 2. 2  内存带宽的影响

    2. 2. 3  躲避内存延迟的其他方法

    2. 2. 4  多线程与预取间的权衡

    2. 3  并行计算平台剖析

    2. 3. 1  并行平台的控制结构

    2. 3. 2  并行平台的通信模型

    2. 4  并行平台的物理组织

    2. 4. 1  理想并行计算机的体系结构

    2. 4. 2  并行计算机互连网络

    2. 4. 3  网络拓扑结构

    2. 4. 4  静态互连网络评价

    2. 4. 5  动态互连网络评价

    2, 4. 6  多处理器系统中的高速

    缓存一致性

    2. 5  并行计算机的通信成本

    2. 5. 1  并行计算机的消息传递成本

    2. 5. 2  共享地址空间计算机的通信成本

    2. 6  互连网络的路由选择机制

    2. 7  进程-处理器映射的影响和映射技术

    2. 7. 1  图的映射技术

    2. 7. 2  成本-性能平衡

    2. 8  书目评注

    习题

    第3章  并行算法设计原则

    3. 1  预备知识

    3. 1. 1  分解. 任务与依赖图

    3. 1. 2  粒度. 并发性与任务交互

    3. 1. 3  进程和映射

    3. 1, 4  进程与处理器

    3. 2  分解技术

    3. 2. 1  递归分解

    3. 2. 2  数据分解

    3. 2. 3  探测性分解

    3. 2. 4  推测性分解

    3. 2. 5  混合分解

    3. 3  任务和交互的特点

    3. 3. 1  任务特性

    3. 3. 2  任务间交互的特征

    3. 4  负载平衡的映射技术

    3. 4. 1  静态映射方案

    3. 4. 2  动态映射方案

    3. 5  包含交互开销的方法

    3. 5. 1  最大化数据本地性

    3. 5. 2 最小化争用与热点

    3. 5. 3  使计算与交互重叠

    3. 5. 4  复制数据或计算

    3. 5. 5  使用最优聚合交互操作

    3. 5. 6  一些交互与另一些交互的重叠

    3. 6  并行算法模型

    3. 6. 1  数据并行模型

    3. 6. 2  任务图模型

    3. 6. 3  工作池模型

    3. 6. 4  主-从模型

    3. 6. 5  流水线模型或生产者-消费者

    模型

    3. 6. 6  混合模型

    3. 7  书目评注

    习题

    第4章  基本通信操作

    4. 1  一对多广播以及多对一归约

    4. 1. 1  环或线性阵列

    4. 1. 2  格网

    4. 1. 3  超立方体

    4. 1. 4  平衡二叉树

    4. 1. 5  算法细节

    4. 1. 6  成本分析

    4. 2  多对多广播和归约

    4. 2. 1  线性阵列和环

    4. 2. 2  格网

    4. 2. 3  超立方体

    4. 2. 4  成本分析

    4. 3  全归约与前缀和操作

    4. 4  散发和收集

    4. 5  多对多私自通信

    4. 5. 1  环

    4. 5. 2  格网

    4. 5. 3  超立方体

    4. 6  循环移位

    4. 6. 1  格网

    4. 6. 2  超立方体

    4. 7  提高某些通信操作的速度

    4. 7. 1  消息分裂和路由选择

    4. 7. 2  全端口通信

    4. 8  小结

    4. 9  书目评注

    习题

    第5章  并行程序的解析建模

    5. 1  并行程序中的开销来源

    5. 2  并行系统的性能度量

    5. 2. 1  执行时间

    5. 2. 2  总并行开销

    5. 2. 3  加速比

    5. 2. 4  效率

    5. 2. 5  成本

    5. 3  粒度对性能的影响

    5. 4  并行系统的可扩展性

    5. 4. 1  并行程序的扩展特性

    5. 4. 2  可扩展性的等效率度量

    5. 4. 3  成本最优性和等效率函数

    5. 4. 4  等效率函数的下界

    5. 4. 5  并发度和等效率函数

    5. 5  最小执行时间和最小成本

    最优执行时间

    5. 6  并行程序渐近分析

    5. 7  其他可扩展性的度量

    5. 8  书目评注

    习题

    第6章  使用消息传递模式编程

    6. 1  消息传递编程的原理

    6. 2  操作构件:发送和接收操作

    6. 2. 1  阻塞式消息传递操作

    6. 2. 2  无阻塞式消息传递操作

    6. 3  MPI:消息传递接口

    6. 3. 1  启动和终止MPI库

    6. 3. 2  通信器

    6. 3. 3  获取信息

    6. 3. 4  发送和接收消息

    6. 3. 5  实例:奇偶排序

    6. 4  拓扑结构与嵌入

    6. 4. 1  创建和使用笛卡儿拓扑结构

    6. 4. 2  实例:Cannon的矩阵与矩阵相乘

    6. 5  计算与通信重叠

    6. 6  聚合的通信和计算操作

    6. 6. 1  障碍

    6. 6. 2  广播

    6. 6. 3  归约

    6. 6. 4  前缀

    6. 6. 5  收集

    6. 6. 6  散发

    6. 6. 7  多对多

    6. 6. 8  实例:一维矩阵与向量相乘

    6. 6. 9  实例:单源最短路径

    6. 6. 10  实例:样本排序

    6. 7  进程组和通信器

    6. 8  书目评注

    习题

    第7章  共享地址空间平台的编程

    7. 1  线程基础

    7. 2  为什么要用线程

    7. 3  POSIX线程API

    7. 4  线程基础:创建和终止

    7. 5  Pthreads中的同步原语

    7. 5. 1  共享变量的互斥

    7. 5. 2  用于同步的条件变量

    7. 6  控制线程及同步的属性

    7. 6. 1  线程的属性对象

    7. 6. 2  互斥锁的属性对象

    7. 7  线程注销

    7. 8  复合同步结构

    7. 8. 1  读-写锁

    7. 8. 2  障碍

    7. 9  设计异步程序的技巧

    7. 10  OpenMP:基于命令的并行

    编程标准

    7. 10. 1  OpenMP编程模型

    7. 10. 2  在OpenMP中指定并发任务

    7. 10. 3  OpenMP中的同步结构

    7. 10. 4  OpenMP中的数据处理

    7. 10. 5  OpenMP库函数

    7. 10. 6  OpenMP中的环境变量

    7. 10. 7  显式线程与基于OpenMP编程

    的比较

    7. 11  书目评注

    习题

    第8章  稠密矩阵算法

    8. 1  矩阵向量乘法

    8. 1. 1  一维行划分

    8. 1. 2  二维划分

    8. 2  矩阵与矩阵的乘法

    8. 2. 1  简单的并行算法

    8. 2. 2  Cannon算法

    8. 2. 3  DNS算法

    8. 3  线性方程组求解

    8. 3. 1  简单高斯消元算法

    8. 3. 2  带部分主元选择的高斯消元算法

    8. 3. 3  求解三角系统:回代法

    8. 3. 4  求解线性方程组时的数值因素

    8. 4  书目评注

    习题

    第9章  排序

    9. 1  并行计算机中的排序问题

    9. 1. 1  输入输出序列的存放位置

    9. 1. 2  如何进行比较

    9. 2  排序网络

    9. 2. 1  双调排序

    9. 2. 2  将双调排序映射到超立方体

    和格网

    9. 3  冒泡排序及其变体

    9. 3. 1  奇偶转换

    9. 3. 2  希尔排序

    9. 4  快速排序

    9. 4. 1  并行快速排序

    9. 4. 2  用于CRCWPRAM的并行形式

    9. 4. 3  用于实际体系结构的并行形式

    9. 4. 4  主元选择

    9. 5  桶和样本排序

    9. 6  其他排序算法

    9. 6. 1  枚举排序

    9. 6. 2  基数排序

    9. 7  书目评注

    习题

    第10章  图算法

    10. 1  定义和表示

    10. 2  最小生成树:Prim算法

    10. 3  单源最短路径:Dijkstra算法

    10. 4  全部顶点对间的最短路径

    10. 4. 1  Dijkstra算法

    10. 4. 2  Floyd算法

    10. 4. 3  性能比较

    10. 5  传递闭包

    10. 6  连通分量

    10. 7  稀疏图算法

    10. 7. 1  查找最大独立集

    10. 7. 2  单源最短路径

    10. 8  书目评注

    习题

    第11章  离散优化问题的搜索算法

    11. 1  定义与实例

    11. 2  顺序搜索算法

    11. 2. 1  深度优先搜索算法

    11. 2. 2  最佳优先搜索算法

    11. 3  搜索开销因子

    11. 4  并行深度优先搜索

    11. 4. 1  并行DFS的重要参数

    11. 4. 2  并行DFS分析的一般框架

    11. 4. 3  负载平衡方案分析

    11. 4. 4  终止检测

    11. 4. 5  试验结果

    11. 4. 6  深度优先分支定界搜索的

    并行形式

    11. 4. 7  IDA*的并行形式

    11. 5  并行最佳优先搜索

    11. 6  并行搜索算法的加速比异常

    11. 7  书目评注

    习题

    第12章  动态规划

    12. 1  动态规划概述

    12. 2  串行一元DP形式

    12. 2. 1  最短路径问题

    12. 2. 2  0/1背包问题

    12. 3  非串行一元DP形式

    12. 4  串行多元DP形式

    12. 5  非串行多元DP形式

    12. 6  综述与讨论

    12. 7  书目评注

    习题

    第13章  快速傅里叶变换

    13. 1  串行算法

    13. 2  二进制交换算法

    13. 2. 1  全带宽网络

    13. 2. 2  有限带宽网络

    13. 2. 3  并行快速傅里叶变换中的

    额外计算

    13. 3  转置算法

    13. 3. 1  二维转置算法

    13. 3. 2  转置算法的推广

    13. 4  书目评注

    习题

    附录A  函数的复杂度与阶次分析

    索引

    并行计算导论(原书第2版) 清晰PDF可以从以下信息下载:

    点击这个http://www.linuxidc.com/Linux/2013-12/93755.htm 链接关注 Linux公社官方微信,关注后回复数字141882。即可得到网友的分享密码。

    如果取消关注Linux公社公众号,即使再次关注,也将无法提供本服务!

    ------------------------------------------分割线------------------------------------------

    也可以到Linux公社1号FTP服务器下载

    用户名:ftp1.linuxidc.com

    密码:www.linuxidc.com

    在 2017年LinuxIDC.com/3月/并行计算导论(原书第2版) 清晰PDF/

    ------------------------------------------分割线------------------------------------------

    0b1331709591d260c1c78e86d0c51c18.png

    展开全文
  • java8函数式编程 pdf

    2021-02-12 22:02:58
    java8函数式编程 pdf的重要性就不言而喻了吧。对于每一个JAVA开发者,这都是一个必过的坎。虽然现在的主流编程方式还是面向对象式。当然也不能否认这种方式的健壮性,可扩展性。但是随着编程技术的发展。走在时代...
  • 第2章 并行编程平台 2.1 隐式并行:微处理器体系结构的发展趋势 2.1.1 流水线与超标量执行 2.1.2 超长指令字处理器 2.2 内存系统性能的局限 2.2.1 使用高速缓存改善有效内存延迟 2.2.2 内存带宽的影响 2.2.3 ...
  • 《Java并发编程实战》深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及...
  • 第二章:使用GPU理解并行计算 2021年8月20日星期五 本章讨论了串行计算修改成并行计算的一般设计方法,较为抽象。但提供了很多研究线索。 1、 GPU中块的数量,一般是SM数量的816倍(每个SM能并发调度816个线程块); ...
  • 《大规模并行处理器编程实战》学习,其他章节关注专栏 CUDA C 线程组成线程块,线程块组成线程网格,线程网格就是kernel。一个kernel中的所有线程都执行相同的代码,区别在于不同的线程属于不同的块(有不同的...
  • 为了充分利用多核处理器的硬件资源和计算能力来提高图像匹配应用的实时性,通过对自适应阈值SSDA图像匹配算法原理的分析,基于任务分解的多核并行编程模式思想,设计了一种自适应阈值SSDA图像匹配并行算法,并在多核...
  • Tcl_TK编程权威指南pdf

    热门讨论 2011-03-25 09:30:55
    Tcl_TK编程权威指南pdf 内容简介回到顶部↑Tcl/Tk是第一种能通过Windows、Macintosh和Solaris等主要平台处理企业级任务的脚本语言。本书共分为55章,依次详细讲述了Tcl基础、Tcl高级特性、TK基础、TK组件、TK详解、...
  • 第四,介绍并行的基本设计模式及Java8对并行程序的支持和改进。第五,介绍高并发框架Akka的使用方法。最后,详细介绍并行程序的调试方法。 实战Java高并发程序设计内容丰富,实例典型,实用性强,适合有一定Java基础...
  • 异构并行编程模型

    2015-06-26 17:18:00
    异构并行编程模型研究与进展[J].软件学报,2014, 25(7): 1459-1475.http://www.jos.org.cn/1000-9825/4608.html LIU Ying, LÜ Fang, WANG Lei, CHEN Li, CUI Hui-Min, FENG Xiao-Bing. Research on Heter...
  • 并行编程入门

    千次阅读 2016-10-14 20:10:38
    1. 并行编程简介 2. MapReduce 2.1 MapReduce简介 2.2 MapReduce框架 2.3 Hadoop介绍 2.4 Hadoop基本类 2.5 Hadoop编程实例1.并行编程简介1.1.并行编程作用,用途商业用途,科学计算,大数据分析1.2....
  • 《Java并发编程实战》PDF版本下载

    千次阅读 2021-02-12 09:43:04
    5.2.3 Copy On Write Array List 5.3 阻塞队列和生产者-消费者模式 5.3.1 示例:桌面搜索 5.3.2 串行线程封闭 5.3.3 双端队列与工作密取 5.4 阻塞方法与中断方法 5.5 同步工具类 5.5.1 闭锁 5.5.2 Future ...
  • Java并发编程实践 PDF 高清版

    热门讨论 2010-06-25 10:44:59
    本书的读者是那些具有一定Java编程经验的程序员、希望了解Java SE 5,6在线程技术上的改进和新特性的程序员,以及Java和并发编程的爱好者。 目录 代码清单 序 第1章 介绍 1.1 并发的(非常)简短历史 1.2 线程的...
  • 提出一种统一的并行计算模型LogGP-U(Unified LogGP),它是一个基于LogGP的并行计算模型,给出在几种...用这个模型分析了cannon矩阵乘在几种编程模式下的理论性能,并在曙光4000A集群上进行验证LogGP-U模型的有效性。
  • Java设计模式及实践.pdf下载资料简介:本书向读者展示Java语言中更加智能化的编码实例。书中首先介绍面向对象编程(OOP)和函数式编程(FP)范式,然后描述常用设计模式的经典使用方法,并解释如何利用函数式编程特性...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,912
精华内容 4,764
热门标签
关键字:

并行编程模式pdf