JUC包工具类介绍二

编程入门 行业动态 更新时间:2024-10-24 08:20:00

JUC包<a href=https://www.elefans.com/category/jswz/34/1770073.html style=工具类介绍二"/>

JUC包工具类介绍二

JUC包工具类介绍二

异步任务

Callable

Callable接口定义一个异步任务,当Callable接口提交到ExecutorService进行异步执行时,返回结果通过Java Future获取。Callable接口同样可以获取任务执行时的异常。

public class MyCallable implements Callable<String> {

    @Override

    public String call() throws Exception {

        return String.valueOf(System.currentTimeMillis());

    }

}

Callable 和 Runnable的区别:

两者都表示一个可以被其他线程执行的任务。Runnable的run方法没有返回值,任务发起线程也无法获取到任务执行中的已检查异常,只能获取到RuntimeException.而Callable可以获取返回值和异常。两者的设计上Runable是为了长时间的并发任务而设计,如网络连接,监听文件等。而Callable适合于返回一个结果的单次任务。

Java Future

Future表示一个异步计算的结果。当异步任务创建之后如Callable提交给ExecutorService之后,返回Future对象,Future接口提供获对异步任务的交互方法,如获取结果,取消任务等,检查任务状态。

public interface Future<V> {

    boolean cancel(boolean mayInterruptIfRunning)

    V       get();

    V       get(long timeout, TimeUnit unit);

    boolean isCancelled();

    boolean isDone();

}

       锁用于避免资源竞争带来的异常。相比于Synchronized,可以提供线程资源唤醒顺序(公平锁),更细粒度的作用于(Synchronized只能作用于整个方法,Lock通过Lock和unLock方法控制),更丰富的控制(如等待超时等参数)

ReentrantLock

       ReentrantLock是一个可重入锁的实现, 可重入锁表示持有锁的现成可以重新获取对锁进行锁定,相应的多次的锁定需要进行多次的unLock。

Lock lock = new ReentrantLock();

lock.lock();

    //critical section

lock.unlock();

公平锁: 公平锁是指等待锁的现成获取锁的顺序按照等待的顺序进行,而非公平锁表示不保证获取顺序。ReentrantLock创建时可以指定是否公平锁。公平锁必须使用带超时的tryLock方法。

ReadWriteLock

       读写锁则是针对读写业务特性设计的锁。保证多线程可以同时读,但当存在写操作时,只能有一个线程持有,此时读操作也无法获取锁。

       Read Lock: 如果当前没有写锁被占有,并且没有写锁的请求,则多线程可以获取读锁进行读操作。

       Write Lock: 如果当前没有现成在进行读或写,只有一个线程可以锁定写锁。

       JUC 下的读写锁实现:ReentrantReadWriteLock

ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

readWriteLock.readLock().lock();

readWriteLock.readLock().unlock();

readWriteLock.writeLock().lock();

readWriteLock.writeLock().unlock();

Atomic系列

       Atomic系列对象提供了针对特定类型提供原子性操作的操作方法。主要是针对于单一操作因为Java字节码分析后实际是多个操作执行的原因,在并发环境下结果可能异常的情况。

AtomicBoolean\ AtomicInteger\ AtomicLong

       提供了可以原子性对boolean变量进行读写操作,已经compareAndSet等高作操作的原子性。

AtomicBoolean atomicBoolean = new AtomicBoolean(true);

boolean value = atomicBoolean.get();

atomicBoolean.set(false);

boolean oldValue = atomicBoolean.getAndSet(false);

boolean expectedValue = true;

boolean newValue      = false;

boolean wasNewValueSet = atomicBooleanpareAndSet(

    expectedValue, newValue);

       AtomicInteger和AtomicLong类型类似。

AtomicReference\AtomicStampedReference

       AtomicReference 保证多线程对对象引用改变不会出现一个不一致的状态。

AtomicReference atomicReference =

     new AtomicReference();

   

atomicReference.set("New object referenced");

boolean exchanged = atomicStringReferencepareAndSet(initialReference, newReference);

      

AtomicStampedReference则是为解决ABA问题而设计的。 ABA问题指的是当前对象是A,经过改变设置为B之后,又重新设置为A, 使用传统的compareAndSet方法进行设置时无法意识到A-B-A的改变过程而误认为对象一直为A没有改变过,从而进行了错误的操作。

AtomicStampedReference对引用的状态添加了时间戳的概念, 对象的完整状态必须包括对象本身以及设置时候的时间戳,因此即使是同一个值,不同的时间戳也就表示不同的状态。

String initialRef   = "initial value referenced";

int    initialStamp = 0;

AtomicStampedReference<String> atomicStringReference =

    new AtomicStampedReference<String>(

        initialRef, initialStamp

    );

String newRef   = "new value referenced";

int    newStamp = initialStamp + 1;

boolean exchanged = atomicStringReference

    pareAndSet(

        initialRef, newRef,

        initialStamp, newStamp);

System.out.println("exchanged: " + exchanged);  //true

exchanged = atomicStringReference

    pareAndSet(

        initialRef, "new string",

        newStamp, newStamp + 1);

System.out.println("exchanged: " + exchanged);  //false

exchanged = atomicStringReference

    pareAndSet(

        newRef, "new string",

        initialStamp, newStamp + 1);

System.out.println("exchanged: " + exchanged);  //false

exchanged = atomicStringReference

    pareAndSet(

        newRef, "new string",

        newStamp, newStamp + 1);

System.out.println("exchanged: " + exchanged);  //true

AtomicIntegerArray\AtomicLongArray\AtomicReferenceArray

AtomicIntegerArray 数组对象系列表示可以进行原子操作的数组。包括AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。

int[] ints = new int[10];

ints[5] = 123;

AtomicIntegerArray array = new AtomicIntegerArray(ints);

int value = array.get(5);

array.set(5, 999);

boolean swapped = arraypareAndSet(5, 999, 123);

int newValue = array.addAndGet(5, 3);

CopyOnWriteArrayList\ CopyOnWriteArraySet

提供线程安全的ArrayList对象,实现上将对ArrayList的所有更新操作都作用在一个写副本上,并且通过ReentrantLock来保护并发更新。Set方法的源码如下:

public E set(int index, E element) {

        final ReentrantLock lock = this.lock;

        lock.lock();

        try {

            Object[] elements = getArray();

            E oldValue = get(elements, index);

            if (oldValue != element) {

                int len = elements.length;

                //拷贝副本进行更新操作,并将新的副本设置为最新列表

                Object[] newElements = Arrays.copyOf(elements, len);

                newElements[index] = element;

                setArray(newElements);

            } else {

                // Not quite a no-op; ensures volatile write semantics

                setArray(elements);

            }

            return oldValue;

        } finally {

            lock.unlock();

        }

    }

CopyOnWriteArraySet提供线程安全的Set操作,底层使用CopyOnWriteArrayList实现。

更多推荐

JUC包工具类介绍二

本文发布于:2023-11-15 20:32:34,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1605917.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:工具   JUC

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!