04Java并发编程
文章
01 Java并发实现
java并发实现1 并发实现3中基本方法和4中拓展方法。 使用线程的3中基本方法 实现 Runnable 接口; 实现 Callable 接口; 继承 Thread 类。 使用四种拓展的方法 匿名内部类 ThreadPool&Executor 定时器timer stream 实现 Runnable 和 Callable 接口的类只能当做一个可以在线程中运行的任务,不是真正意义上的线程,因此最后还需要通过 Thread 来调用。 通过线程驱动执行线程任务 实现 Runnable 接口需要实现接口中的 run() 方法。 123456public class MyRunnable implements Runnable { @Override public void run() { // ... }} 使用 Runnable 实例再创建一个 Thread 实例,然后调用 Thread 实例的 start() 方法来启动线程。 12345public static void main(String...
02 Java互斥同步
1 互斥访问Java 提供了两种锁机制来控制多个线程对共享资源的互斥访问,第一个是 JVM 实现的 synchronized,而另一个是 JDK 实现的 ReentrantLock。 synchronized1. 同步一个代码块 12345public void func() { synchronized (this) { // ... }} 它只作用于同一个对象,如果调用两个对象上的同步代码块,就不会进行同步。 对于以下代码,使用 ExecutorService 执行了两个线程,由于调用的是同一个对象的同步代码块,因此这两个线程会进行同步,当一个线程进入同步语句块时,另一个线程就必须等待。 12345678910public class SynchronizedExample { public void func1() { synchronized (this) { for (int i = 0; i < 10; i++) ...
03 Java进程通信
1 PipePipedReader是Reader类的扩展,用于读取字符流。 它的read()方法读取连接的PipedWriter的流。 同样, PipedWriter是Writer类的扩展,它完成Reader类所收缩的所有工作。 读线程 1234567891011121314151617181920212223242526public class PipeReaderThread implements Runnable { PipedReader pr; String name = null; public PipeReaderThread(String name, PipedReader pr) { this.name = name; this.pr = pr; } public void run() { try { // continuously read data from stream and print ...
04 Java线程池
1 Executor概述概述Executor framework框架由三个主要接口(以及许多子接口)组成,即Executor , ExecutorService和ThreadPoolExecutor 。 该框架主要将任务创建和执行分开。 任务创建主要是样板代码,并且很容易替换。 对于执行者,我们必须创建实现Runnable或Callable接口的任务,并将其发送给执行者。 执行程序在内部维护一个(可配置的)线程池,以通过避免连续产生线程来提高应用程序性能。 执行程序负责执行任务,并使用池中的必要线程运行它们。 分类Executor 管理多个异步任务的执行,而无需程序员显式地管理线程的生命周期。这里的异步是指多个任务的执行互不干扰,不需要进行同步操作。 CachedThreadPool:缓存线程池执行程序 –创建一个线程池,该线程池可根据需要创建新线程,但在可用时将重用以前构造的线程。 如果任务长时间运行,请勿使用此线程池。 如果线程数超出系统可以处理的范围,则可能导致系统崩溃。 FixedThreadPool:固定线程池执行程序 –创建一个线程池,该线程池可重用固定数量的线...
05 JUC并发组件
1 J.U.C - AQSjava.util.concurrent(J.U.C)大大提高了并发性能,AQS 被认为是 J.U.C 的核心。 ReentrantLock:lock/unlockReentrantLock 是 java.util.concurrent(J.U.C)包中的锁。 123456789101112131415public class LockExample { private Lock lock = new ReentrantLock(); public void func() { lock.lock(); try { for (int i = 0; i < 10; i++) { System.out.print(i + " "); } } finally { lock.unlock(); // 确保释放锁,...
06 JUC并发容器
2 J.U.C -并发容器并发集合是指使用了最新并发能力的集合,在JUC包下。而同步集合指之前用同步锁实现的集合。 其对应的基础集合类的接口并没有发生太大变化,主要是针对并发场景进行优化,使用各种方式保证并发集合的安全性。 1 CopyOnWriteCopyOnWriteArrayListCopyOnWriteArrayList在写的时候会复制一个副本,对副本写,写完用副本替换原值,读的时候不需要同步,适用于写少读多的场合。 CopyOnWriteArraySet基于CopyOnWriteArrayList来实现的,只是在不允许存在重复的对象这个特性上遍历处理了一下。 读写分离写操作在一个复制的数组上进行,读操作还是在原始数组中进行,读写分离,互不影响。 写操作需要加锁,防止并发写入时导致写入数据丢失。 写操作结束之后需要把原始数组指向新的复制数组。 123456789101112131415161718public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); ...
07 Java线程安全
Java 并发1 线程安全概述线程不安全示例如果多个线程对同一个共享数据进行访问而不采取同步操作的话,那么操作的结果是不一致的。 以下代码演示了 1000 个线程同时对 cnt 执行自增操作,操作结束之后它的值有可能小于 1000。 123456789101112public class ThreadUnsafeExample { private int cnt = 0; public void add() { cnt++; } public int get() { return cnt; }} 123456789101112131415public static void main(String[] args) throws InterruptedException { final int threadSize = 1000; ThreadUnsafeExample example = new ThreadUnsafeExample();...
08 Java内存模型
内存模型1 Java 内存模型Java 内存模型试图屏蔽各种硬件和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的内存访问效果。 主内存与工作内存处理器上的寄存器的读写的速度比内存快几个数量级,为了解决这种速度矛盾,在它们之间加入了高速缓存。 加入高速缓存带来了一个新的问题:缓存一致性。如果多个缓存共享同一块主内存区域,那么多个缓存的数据可能会不一致,需要一些协议来解决这个问题。 所有的变量都存储在主内存中,每个线程还有自己的工作内存,工作内存存储在高速缓存或者寄存器中,保存了该线程使用的变量的主内存副本拷贝。 线程只能直接操作工作内存中的变量,不同线程之间的变量值传递需要通过主内存来完成。 内存间交互操作Java 内存模型定义了 8 个操作来完成主内存和工作内存的交互操作。 read:把一个变量的值从主内存传输到工作内存中 load:在 read 之后执行,把 read 得到的值放入工作内存的变量副本中 use:把工作内存中一个变量的值传递给执行引擎 assign:把一个从执行引擎接收到的值赋给工作内存的变量 store:把工作内存的一个变量的...
09 Java锁优化
1 锁优化这里的锁优化主要是指 JVM 对 synchronized 的优化。 自旋锁互斥同步进入阻塞状态的开销都很大,应该尽量避免。在许多应用中,共享数据的锁定状态只会持续很短的一段时间。自旋锁的思想是让一个线程在请求一个共享数据的锁时执行忙循环(自旋)一段时间,如果在这段时间内能获得锁,就可以避免进入阻塞状态。 自旋锁虽然能避免进入阻塞状态从而减少开销,但是它需要进行忙循环操作占用 CPU 时间,它只适用于共享数据的锁定状态很短的场景。 在 JDK 1.6 中引入了自适应的自旋锁。自适应意味着自旋的次数不再固定了,而是由前一次在同一个锁上的自旋次数及锁的拥有者的状态来决定。 锁消除锁消除是指对于被检测出不可能存在竞争的共享数据的锁进行消除。 锁消除主要是通过逃逸分析来支持,如果堆上的共享数据不可能逃逸出去被其它线程访问到,那么就可以把它们当成私有数据对待,也就可以将它们的锁进行消除。 对于一些看起来没有加锁的代码,其实隐式的加了很多锁。例如下面的字符串拼接代码就隐式加了锁: 123public static String concatString(String s1, Str...
11 Java只执行一次
问题说明有时我们希望java程序能在高并发操作下,某个函数只执行一次。 一般情况下,设置一个门控值,每次执行前检查是否执行过,如果没有执行过,则设置为false,并执行。如果为true则不执行。如果是单线程,该方法能够发挥作用。 多线程情况下,如果多个线程同时判断门控值,都得到true,就会同时进入执行结果。 1 高并发下的原子操作使用一个原子Boolean值作为门控值。同一时间进入判断的值只有一个,能保证多线程情况下,该函数仍然只执行一次。 123456789101112private AtomicBoolean inited = new AtomicBoolean(false);/** * @see ServerManager#getServerList() */@Overridepublic List<ServerNode> getServerList() { if (inited.compareAndSet(false, true)) { initServerList(); }...













