`

多线程摘录 003

阅读更多
同步器
A synchronizer is any object that coordinates the control flow of threads based on its state. Blocking queues can act as synchronizers; other types of synchronizers include semaphores, barriers, and latches

Latch
Latch是门闩的意思, 一旦关闭(打开), 就保持这个状态, 一直不变.
用脚指头也能想到用来干什么了: 保证某些动作只执行一次! 在应用上就广泛一些, 比如初始化某个对象, 在有依赖关系的任务流里面控制执行顺序等

CoutDownLatch是一种Latch实现, 允许多个线程等待一组事件的发生.
下面这一小段代码是为了统计一个任务N次运行的平均时间. 不能采用new Thread().start()的方式, 那样的话, 早建立的线程就先运行完毕, 统计不精确.

public class TestHarness {
    public long timeTasks(int nThreads, final Runnable task)
            throws InterruptedException {
        final CountDownLatch startGate = new CountDownLatch(1);
        final CountDownLatch endGate = new CountDownLatch(nThreads);

        for (int i = 0; i < nThreads; i++) {
            Thread t = new Thread() {
                public void run() {
                    try {
                        startGate.await();
                        try {
                            task.run();
                        } finally {
                            endGate.countDown();
                        }
                    } catch (InterruptedException ignored) { }
                }
            };
            t.start();
        }

        long start = System.nanoTime();
        startGate.countDown();
        endGate.await();
        long end = System.nanoTime();
        return end-start;
    }
}


FutureTask
FutureTask的行为也像是Latch, 一旦任务完成返回了Future的结果, 就不再改变.
public class Preloader {
    private final FutureTask<ProductInfo> future =
        new FutureTask<ProductInfo>(new Callable<ProductInfo>() {
            public ProductInfo call() throws DataLoadException {
                return loadProductInfo();
            }
        });
    private final Thread thread = new Thread(future);

    public void start() { thread.start(); }

    public ProductInfo get()
            throws DataLoadException, InterruptedException {
        try {
            return future.get();
        } catch (ExecutionException e) {
            ...
        }
    }
}

当其他方法调用Preloader.get()的时候, 如果任务未完成, 会阻塞, 否则直接返回结果, 但是结果不再改变

Semaphore
简而言之, Semaphore控制许可证的数量. 当可用许可证的数量为0, acquire()就阻塞. release()可以把一个许可还给Semaphore. 如果许可证的数量为1, 其实就成了一个互斥体(mutex), 和synchronized的作用相同.

Barrier
The key difference is that with a barrier, all the threads must come together at a barrier point at the same time in order to proceed. Latches are for waiting for events; barriers are for waiting for other threads.
其实Barrier和Latch是很相似的...   (TODO: 这里说明的差别很模糊, 怎么具体来比较呢?)

例子可以参考JDK5的API手册. CyclicBarrier是Barrier的一个实现类, 和Latch不同的是, 它可以被reset, 从而重新使用, Latch则是到达最终状态后不再改变

小技巧:
如果想按照系统的CPU数量来分配线程数, 怎么做? 很简单, Runtime类能告诉我们:
Runtime.getRuntime().availableProcessors()

一个并发的Cache
这个Cache的设计很有意思, 考虑了很多并发的因素. Cache用简单的Map方式来实现.
1) 使用ConcurrentHashMap来存放计算结果
2) 最有趣的一点, ConcurrentHashMap里存放的内容是FutureTask. (知道为什么? 这相当于放一个Latch)
3) 使用了FutureTask来调度计算, 这样多个线程可以分别进行针对不同的参数的计算
4) 基于FutureTask的特性, 先把FutureTask放进了cache, 再对FutureTask计算
5) 用来一个 while(true) 无限循环...
    ???? 这是为什么? 因为如果发现已经有一个线程中进行相同的计算的话, 就直接等待计算结果. 但是等待过程中, 如果FutureTask被中断了呢? 抓住异常, 再等...
6) 使用putIfAbsent操作, 避免出现两个线程都进行相同的计算

public class Memoizer<A, V> implements Computable<A, V> {
    private final ConcurrentMap<A, Future<V>> cache
        = new ConcurrentHashMap<A, Future<V>>();
    private final Computable<A, V> c;

    public Memoizer(Computable<A, V> c) { this.c = c; }

    public V compute(final A arg) throws InterruptedException {
        while (true) {
            Future<V> f = cache.get(arg);
            if (f == null) {
                Callable<V> eval = new Callable<V>() {
                    public V call() throws InterruptedException {
                        return c.compute(arg);
                    }
                };
                FutureTask<V> ft = new FutureTask<V>(eval);
                f = cache.putIfAbsent(arg, ft); //先把FutureTask放进去再说
                if (f == null) { f = ft; ft.run(); } //开始计算
            }
            try {
                return f.get();
            } catch (CancellationException e) {
                cache.remove(arg, f);
            } catch (ExecutionException e) {
                throw launderThrowable(e.getCause());
            }
        }
    }
}


想象一下自己以前写的(呵呵, 简单易懂, 绝对能工作, 但并发性能就...)
public synchronized Object get(Object k) {
    Object obj = cache.get(k);
    if (obj==null) {
        obj = loadFromDB(k);
        cache.put(k, obj);
    }
    return obj;
}

转自:http://hi.baidu.com/iwishyou2/blog/item/2df183ece3062135279791e0.html

分享到:
评论

相关推荐

    delphi多线程编程学习

    在Delphi编程环境中,多线程技术是一种强大的工具,它允许程序同时执行多个任务,从而提高应用程序的响应性和效率。本教程将引导你深入理解Delphi中的多线程编程,并通过实例来帮助你掌握相关技能。 一、多线程概念...

    c语言多进程多线程编程.pdf

    《C语言多进程多线程编程》是一本深入探讨C语言在并发编程领域的专业书籍。在计算机科学中,进程和线程是操作系统中并行执行任务的基本单位,理解和掌握它们对于提升程序性能和优化资源利用至关重要。这本书籍针对...

    C#下多线程实现实例----一个图形化的排序算法演示程序.pdf

    从内容摘录中无法直接得知程序是如何处理线程同步问题的,但可以确定在多线程环境中运行排序算法时,这一点尤为重要。 图形化展示排序过程的核心是ShowData方法。这个方法使用了Windows Forms中的Graphics类来绘制...

    一个很不错的VC++ 多线程应用例子

    摘要:VC/C++源码,系统相关,多线程 与VC++爱好者们分享一个很不错的多线程MultiThread应用例子,你可将之中的模块摘录出来供需要者使用。本多线程模块实例以新建文件写入数据为操作目的,创建多个线程分别创建文件,...

    《Java与模式 阎宏 摘录》.doc 更新中……

    同时,他可能会讨论Java的特性,如多线程、反射、泛型等,以及这些特性和设计模式的结合使用。 通过对《Java与模式 阎宏 摘录》的学习,开发者不仅可以提升自己的编程技巧,还能深入了解如何在实际工作中选择和应用...

    VB异步执行线程的实例源代码

     A:晕,这最终还是调用了老汉多线程……那和线程也没什么区别吧……你应该再试一试线程池……  B:不完全是,因为纤程要先ConvertThreadToFiber,才能CreateFiber,VB中就一个线程,你把它Convert成纤程,那纤程...

    ucgui源程序摘录

    这部分可能涉及到在多线程环境中保护GUI资源的同步机制。在Windows环境下,可能使用标准的互斥对象来实现这一功能,而在其他环境(如单片机)中,可能需要自定义的解决方案。 总的来说,ucgui是一个提供图形用户...

    C++经典笔试和面试摘录

    包括了c++经典笔试题,多线程编程,操作系统,数据库,网络相关知识。以及一些经典面经

    ACE摘录&总结

    ACE Reactor框架是其核心部分之一,它是一个事件多路分离器,能够在一个进程或线程中处理多个客户端连接的事件。使用Reactor框架开发用户程序相对简单,主要包括三个步骤:首先,从`ACE_Event_Handler`派生出子类并...

    vilatile

    根据提供的文件信息,我们可以推断出这部分内容主要讨论了多线程编程中的关键概念与技术。下面将基于这些有限的信息,展开对多线程编程中的一些核心知识点进行详细阐述。 ### 多线程编程概述 多线程编程是现代软件...

    摘录有关vb的资料

    《精通VB.pdf》:这是一本高级教程,旨在帮助读者从熟悉VB到精通,内容可能涉及更复杂的编程概念和技术,如面向对象编程、高级控件应用、多线程处理、网络编程等,有助于提升编程技能。 《VB-函数-速查手册.pdf》:...

    单例设计模式个人总结+摘录

    2. **控制共享资源的访问**:在多线程环境下,可以确保共享资源被正确地管理,避免资源竞争问题。 3. **简化配置过程**:单例模式下的对象通常作为配置或参数传递给其他对象使用,简化了配置过程。 #### 实现方式 ...

    全国各个软件公司面试题---DOTNET笔试题集(摘录)

    可以通过锁(lock)机制、读写锁、线程静态字段(ThreadStaticAttribute)等方式确保多线程环境下的安全性。 #### 4.3 什么是装箱与拆箱? 装箱是指将值类型转换为引用类型的过程;拆箱则是相反的过程。这在使用泛型...

    资深攻城狮解读5个被误解的CPU/GPU概念

    相反,多线程技术可以在较少核心的情况下提供更好的性能提升,因为它可以在同一核心上同时执行多个线程,增加处理效率,并且在开发难度、功耗和面积上,多线程技术更有优势。作者提出未来CPU发展不应只是在多核上...

    Python语言程序设计教程.pptx

    本资源是关于Python语言程序设计的教程,总共分为10章,涵盖了Python编程语言的基础知识、数据类型、控制结构、函数、模块、文件处理、异常处理、面向对象编程、多线程编程等方面的内容。 第一章至第四章主要介绍了...

    参考文献辅助管理软件CvtCNKI

    线程.rar可能包含的是关于CvtCNKI的多线程下载技术文档,这通常意味着软件可能利用多线程技术加速从CNKI等网站下载文献,提高效率,尤其对于大量文献的下载来说,这是一个非常实用的功能。 CvtCNKI-v2.0.1是软件的...

    C++ Concurrency in Action 完整版

    并发编程是一个广泛的话题,涉及到线程的创建、管理、数据共享、同步、内存模型、设计无锁数据结构、设计基于锁的数据结构、并发代码设计、高级线程管理和多线程应用程序的测试与调试等多个方面。 在描述中,书籍的...

    电子阅读器修正版

    在IT行业中,电子阅读器是一种专门用于阅读电子书的软件或设备,它们通常具有文本...这个修复过程涉及到了C#中对剪贴板的操作、可能的多线程同步问题以及异常处理策略,这些都是开发高质量软件时必须考虑的关键因素。

Global site tag (gtag.js) - Google Analytics