关于java:Java并发程序设计总览学习

45次阅读

共计 3413 个字符,预计需要花费 9 分钟才能阅读完成。

1、应用线程的一些教训

  • 设置名称

    无论何种形式,启动一个线程,就要给它一个名字!这对排错诊断系统监控有帮忙。否则诊断问题时,无奈直观晓得某个线程的用处。

  • 响应中断

    程序应该对线程中断作出失当的响应。

  • 应用 ThreadLocal

    它的功能非常简单,就是为每一个应用该变量的线程都提供一个变量值的正本,是每一个线程都能够独立地扭转本人的正本,而不会和其它线程的正本抵触。从线程的角度看,就如同每一个线程都齐全领有该变量。

    留神:应用 ThreadLocal,个别都是申明在动态变量中,如果一直的创立 ThreadLocal 而且没有调用其 remove 办法,将会导致内存泄露。

2、Executor:ExecutorService 和 Future

为了不便并发执行工作,呈现了一种专门用来执行工作的实现,也就是 Executor。由此,工作提交者不须要再创立治理线程,应用更不便,也缩小了开销。

java.util.concurrent.Executors 是 Executor 的工厂类,通过 Executors 能够创立你所须要的 Executor。

ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Object> task = new Callable < Object > () {public Object call () throws Exception {
        Object result = "...";
        return result;
    }
} ;
Future<Object> future = executor.submit(task);
future.get();

有两种工作:Runnable、Callable,Callable 是须要返回值的工作。

Task Submitter 把工作提交给 Executor 执行,他们之间须要一种通信伎俩,这种伎俩的具体实现,通常叫做 Future。Future 通常包含 get(阻塞至工作实现),cancel,get(timeout)(期待一段时间)等等。Future 也用于异步变同步的场景。

3、阻塞队列: put 和 take、offer 和 poll、drainTo

阻塞队列,是一种罕用的并发数据结构,罕用于生产者 - 消费者模式。
在 Java 中,有三种罕用的阻塞队列:
ArrayBlockingQueue
LinkedBlockingQueue
SynchronousQueue

应用阻塞队列:

Monitor 的实践模型

4、ReentrantLock 和 Synchronized

Synchronized 是 Lock 的一种简化实现,一个 Lock 能够对应多个 Condition,而 synchronized 把 Lock 和 Condition 合并了,一个 synchronizedLock 只对应一个 Condition,能够说 Synchronized 是 Lock 的简化版本。

在 JDK5,Synchronized 要比 Lock 慢很多,然而在 JDK6 中,它们的效率差不多。

5、Lock-free 算法

LockFree 算法,不须要加锁。
通常都是三个局部组成:
①循环
②CAS (CompareAndSet)
③break

进一步应用 Lock-Free 数据结构

class BeanManager {private ConcurrentMap<String, Object> map = new ConcurrentHashMap<String, Object>();

    public Object getBean
            (String key) {Object bean = map.get(key);
        if (bean == null) {map.putIfAbsent(key, createBean());
            bean = map.get(key);
        }
        return bean;
    }
}

ConcurrentHashMap 并没有实现 Lock-Free,只是应用了拆散锁的方法使得可能反对多个 Writer 并发。ConcurrentHashMap 须要应用更多的内存。

同样的思路用于更新数据库 - 乐观锁。

Lock-Free 算法,能够说是乐观锁,如果非强烈竞争的时候,不须要应用锁,从而开销更小,速度更快。

适当应用 CopyOnWriteArrayList,可能进步读操作时的效率。

6、对于锁应用的教训介绍

应用反对 CAS 的数据结构,防止应用锁,如:AtomicXXX、ConcurrentMap、CopyOnWriteList、ConcurrentLinkedQueue

肯定要应用锁的时候,留神取得锁的程序,相同程序取得锁,就容易产生死锁。

死锁常常是无奈完全避免的,鸵鸟策略被很多根底框架所采纳。

通过 Dump 线程的 StackTrace,例如 linux 下执行命令 kill -3 <pid>,或者 jstack–l <pid>,或者应用 Jconsole 连贯下来查看线程的 StackTrace,由此来诊断死锁问题。

内部锁常被忽视而导致死锁,例如数据库的锁

7、并发流程管制伎俩:CountDownlatch、Barrier

并发流程管制 - 应用 CoutDownLatch

final int COUNT = 10;
final CountDownLatch completeLatch = new CountDownLatch(COUNT);
for (int i = 0; i < COUNT; ++i) {Thread thread = new Thread("worker thread" + i) {public void run() {
            // do xxxx
            completeLatch.countDown();}
    };
    thread.start();}
// 当你启动了一个线程,你须要等它执行完结,此时,CountDownLatch 兴许是一个很好的抉择。completeLatch.await();
final CountDownLatch startLatch = new CountDownLatch(1);
for (int i = 0; i < 10; ++i) {Thread thread = new Thread("worker thread" + i) {public void run() {
            try {
                // 当你启动很多线程,你须要这些线程等到告诉后才真正开始,CountDownLatch 兴许是一个很好的抉择。startLatch.await();} catch (InterruptedException e) {return;}
            // do xxxx
        }
    };
    thread.start();}
// do xxx
startLatch.countDown();

Barrier:

屏障是一种协调机制(一种算法),它迫使参加并发(或分布式)算法的过程期待,直到它们中的每一个都达到其程序中的某个点。这些协调点的汇合被称为屏障。一旦所有流程都达到了阻碍,它们都能够持续通过阻碍。

8、定时器

应用定时器 ScheduledExecutorService

java.util.concurrent.Executors 是 ScheduledExecutorService 的工厂类,通过 Executors,你能够创立你所须要的 ScheduledExecutorService。

JDK 1.5 之后有了 ScheduledExecutorService,不倡议你再应用 java.util.Timer,因为它无论性能性能都不如 ScheduledExecutorService。

大规模定时器 TimerWheel

存在一种算法 TimerWheel,实用于大规模的定时器实现。这个算法最早是被设计用来实现 BSD 内核中定时器的,起初被宽泛移植到诸如 ACE 等框架中,堪称 BSD 中经典算法之一,能针对定时器的各类常见操作提供靠近常数工夫的响应,且能依据须要很容易进行扩大。

9、并发三大定律:Amdahl、Gustafson、Sun-Ni

Amdahl 定律

Gene Amdahl 发现在计算机体系架构设计过程中,某个部件的优化对整个架构的优化和改善是有下限的。这个发现起初成为出名的 Amdahl 定律。

Gustafson 定律

Gustafson 假如随着处理器个数的减少,并行与串行的计算总量也是能够减少的。Gustafson 定律认为减速系数简直跟处理器个数成正比,如果现实情况合乎 Gustafson 定律的假如前提的话,那么软件的性能将能够随着解决个数的减少而减少。

Sun-Ni 定律

充分利用存储空间等计算资源,尽量增大问题规模以产生更好 / 更准确的解。

正文完
 0