美文网首页
多线程(juc随笔)1

多线程(juc随笔)1

作者: 云中人山 | 来源:发表于2018-12-18 09:34 被阅读3次

据说在java 1.5之前,如果涉及到多线程的场景,大家只能使用从1.0开始就存在的一个接口: Runnable,
或者说使用实现了Runnabel接口的Thread类


在1.5版本时,Doug Lea 在版本中编写了java.util.concurrent ,让线程的使用变得更加简单
笔者使用的jdk版本为1.9,但是考虑到1.9使用的人不多,在这里还是讨论1.8版本的内容。
在这个版本的java.util.concurrent包内,大致分了一下类:

juc.png

atomic

atomic包内包含有一系列支持原子操作的类,最常用的一般为AtomicBooleanAtomicIntegerAtomicLong
在这些类中,涉及到值的操作,都是调用的Unsafe中对应方法(或者是VarHandle中对应方法,参见Unsafe -> VarHandle

以AtomicInteger为例,这里的addAndGet方法实际调用的是VarHandle#getAndAdd

/**
     * Atomically adds the given value to the current value,
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     *
     * @param delta the value to add
     * @return the updated value
     */
    public final int addAndGet(int delta) {
        return U.getAndAddInt(this, VALUE, delta) + delta;
    }

locks

locks包内包含锁相关的类和接口,比如最核心的lock接口,其主要方法有lock()tryLock()unlock(),这里不做过多介绍

Lock接口

locks包内包含 LockCondition 相关内容

其中Lock接口

* {@code Lock} implementations provide more extensive locking
 * operations than can be obtained using {@code synchronized} methods
 * and statements.  They allow more flexible structuring, may have
 * quite different properties, and may support multiple associated
 * {@link Condition} objects.

简单来说,Lock接口实际上是对 synchronized的一个扩展,并提供了更加灵活的操作,比如其tryLock()方法,并且支持Condition 对象,关于Condition,我们稍后会进行讨论

Lock接口的基本方法有:

void lock();
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();

ReadWriteLock接口

在实际的场景中,大部分的情况下我们是读取数据,并不是修改或者写入数据,而传统的synchronized关键字并不支持对读写场景的区分,在jdk1.5之后也加入了ReadWriteLock接口,提供读写锁的支持

每个读写锁由读锁和写锁构成:

public interface ReadWriteLock {
    /**
     * Returns the lock used for reading.
     *
     * @return the lock used for reading
     */
    Lock readLock();

    /**
     * Returns the lock used for writing.
     *
     * @return the lock used for writing
     */
    Lock writeLock();
}

必须注意的是,所有实现ReadWriteLock实现必须保证,成功获取readLock的线程将看到在先前释放writeLock所做的所有更新

以下内容来自维基百科:

读写锁是计算机程序的并发控制的一种同步机制,也称“共享-互斥锁”、多读者-单写者锁。[[1]](https://zh.wikipedia.org/wiki/%E8%AF%BB%E5%86%99%E9%94%81#cite_note-Hamilton-1)多读者锁,[2],“push lock”[3]) 用于解决读写问题。读操作可并发重入,写操作是互斥的。

线程池相关

Executor

一个Executor应该能执行被提交的Runnable方法,并且这个接口将任务提交和任务执行之间解耦了

实际上,许多Executor的实现类会对任务执行进行调度,并将任务序列化后交给第二个executor,如下所示

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.Executor;

public class SerialExecutor implements Executor {
    final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
    final Executor executor;
    Runnable active;

    SerialExecutor(Executor executor) {
        this.executor = executor;
    }
    @Override
    public synchronized void execute(final Runnable r) {
        tasks.offer(new Runnable() {
            @Override
            public void run() {
                try {
                    r.run();
                } finally {
                    scheduleNext();
                }
            }
        });
        if (active == null) {
            scheduleNext();
        }
    }

    protected synchronized void scheduleNext() {
        if ((active = tasks.poll()) != null) {
            executor.execute(active);
        }
    }
}

Executors

总的来说这个类是线程池的工厂类,提供了多种线程池的生成静态方法


ExecutorService

  • ExecutorService 继承了Executor接口,并且提供了 shutdown()方法来关闭线程池
  • Executor只能接受Runnable任务,而ExecutorService还能接受Callable任务
  • Executorsubmit()方法没有返回值,ExecutorService中提供了Future型的返回值

Future

Future代表一个异步计算的结果,并且提供了对应的方法来判断任务是完成还是取消了,也提供了等待任务完成的方法。

 * interface ArchiveSearcher { String search(String target); }
 * class App {
 *   ExecutorService executor = ...
 *   ArchiveSearcher searcher = ...
 *   void showSearch(final String target)
 *       throws InterruptedException {
 *     Future<String> future
 *       = executor.submit(new Callable<String>() {
 *         public String call() {
 *             return searcher.search(target);
 *         }});
 *     displayOtherThings(); // do other things while searching
 *     try {
 *       displayText(future.get()); // use future
 *     } catch (ExecutionException ex) { cleanup(); return; }
 *   }
 * }}

相关文章

  • 多线程(juc随笔)1

    据说在java 1.5之前,如果涉及到多线程的场景,大家只能使用从1.0开始就存在的一个接口: Runnable,...

  • 2018-07-26 CountDownLatch

    【转】Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例

  • 学习方向

    JAVA基础 多线程、JUC(Java Util Concurrency)、IO、集合 JVM相关 高并发 Spr...

  • juc多线程

    1、join:待此线程执行完成后,再执行其他线程,其他线程阻塞等待 CyclicBarrier 等所有线程都到达了...

  • 并发编程之 CountDown 源码分析

    前言 Doug Lea 大神在 JUC 包中为我们准备了大量的多线程工具,其中包括 CountDownLatch ...

  • ReentrantLock 源码分析以及 AQS (一)

    前言 JDK1.5 之后发布了JUC(java.util.concurrent),用于解决多线程并发问题。AQS ...

  • Java多线程JUC

    1. volatile 关键字 多线程访问的时候,一个比较严重的问题就是内存不可见,其实在内存访问的时候每一个线程...

  • JUC框架&多线程

    5 Volatile 关键字 保证内存可见和有序向性,但是不保证原子性 虽然synchronized,jvm对它做...

  • 多线程juc容器

    java_basic 1 juc容器 collections List Set Map Queue CopyO...

  • 多线程juc锁

    java_basic 1 线程安全 在Java多线程编程当中,实现线程安全: 内部锁(Synchronized...

网友评论

      本文标题:多线程(juc随笔)1

      本文链接:https://www.haomeiwen.com/subject/pulscqtx.html