GVKun编程网logo

java.util.concurrent.locks.LockSupport 源码(java.util.scanner源码)

3

在这里,我们将给大家分享关于java.util.concurrent.locks.LockSupport源码的知识,让您更了解java.util.scanner源码的本质,同时也会涉及到如何更有效地A

在这里,我们将给大家分享关于java.util.concurrent.locks.LockSupport 源码的知识,让您更了解java.util.scanner源码的本质,同时也会涉及到如何更有效地AG 百家乐最新官网《 787977.tv 蝙蝠 14735340 》java 并发编程 (2):Java 多线程 - java.util.concurrent 高级工具、Android-Studio-2.3错误:java.util.concurrent.ExecutionException:java.lang.RuntimeException:AAPT进程尚未准备好接收命令、com.intellij.util.ReflectionUtil 对方法 java.util.ResourceBundle.setParent(java.util.ResourceBundle) 的非法反射访问、CompletableFuture 源码详解之 java.util.concurrent.CompletableFuture#supplyAsync (java.util.function.Suppl...的内容。

本文目录一览:

java.util.concurrent.locks.LockSupport 源码(java.util.scanner源码)

java.util.concurrent.locks.LockSupport 源码(java.util.scanner源码)

LockSupport 主要利用了 Unsafe 类中提供的 part 和 unpart 两个方法.而 LockSupport 类暴露出来的两个核心接口也是 part 和 unpart 两个.

相关类图:

java.util.concurrent.locks.LockSupport 源码:

package java.util.concurrent.locks;

import sun.misc.Unsafe;

public class LockSupport {
    //构造方法私有化
    private LockSupport() {}

    //把Thread实例t的parkBlocker字段的值设置为arg
    private static void setBlocker(Thread t, Object arg) {
        UNSAFE.putObject(t, parkBlockerOffset, arg);
    }

    //获取对象t中parkBlocker字段的值
    public static Object getBlocker(Thread t) {
        if (t == null)
            throw new NullPointerException();
        return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
    }

    //取消阻塞线程,如果线程已经处于非阻塞状态,那么下次调用park时不会阻塞线程
    public static void unpark(Thread thread) {
        if (thread != null)//判断是否为空,然后调用unsafe的unpark
            UNSAFE.unpark(thread);
    }

    // 使当前调用线程在给定对象上阻塞(不能保证一定阻塞,
    // 因为如果之前在非阻塞状态调用了unpark 方法的话,此次调用park方法就不会阻塞线程)
    public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);在调用park阻塞当前线程之前,先记录当前线程的blocker
        UNSAFE.park(false, 0L);//调用park阻塞当前线程
        setBlocker(t, null);//当线程可以继续执行下去时,再将parkBlocker设置为null
    }

    // 使当前线程在blocker对象上阻塞给定的纳秒时间
    public static void parkNanos(Object blocker, long nanos) {
        if (nanos > 0) {
            Thread t = Thread.currentThread();
            setBlocker(t, blocker);
            UNSAFE.park(false, nanos);
            setBlocker(t, null);
        }
    }

    // 使当前线程在blocker对象上阻塞到给定的时间点
    // 这个时间点是从Epoch time(1970-01-01 00:00:00 UTC)开始算起的某个具体的时间点
    public static void parkUntil(Object blocker, long deadline) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(true, deadline);
        setBlocker(t, null);
    }

    
    // 阻塞当前线程
    public static void park() {
        UNSAFE.park(false, 0L);
    }
    
    //在指定的时限前阻塞当前线程    
    public static void parkNanos(long nanos) {
        if (nanos > 0)
            UNSAFE.park(false, nanos);
    }

    // 使当前线程在blocker对象上阻塞到给定的时间点
    // 这个时间点是从Epoch time(1970-01-01 00:00:00 UTC)开始算起的某个具体的时间点
    public static void parkUntil(long deadline) {
        UNSAFE.park(true, deadline);
    }

    //返回伪随机初始化或更新的二级种子
    static final int nextSecondarySeed() {
        int r;
        Thread t = Thread.currentThread();
        if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {
            r ^= r << 13;   // xorshift
            r ^= r >>> 17;
            r ^= r << 5;
        }
        else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0)
            r = 1; // avoid zero
        UNSAFE.putInt(t, SECONDARY, r);
        return r;
    }

    //引用Unsafe类
    private static final sun.misc.Unsafe UNSAFE;
    //Thread类中parkBlocker字段的偏移量
    private static final long parkBlockerOffset;
    //Thread 类中threadLocalRandomSeed字段的偏移量
    private static final long SEED;
    //Thread 类中threadLocalRandomProbe字段的偏移量
    private static final long PROBE;
    //Thread 类中threadLocalRandomSecondarySeed字段的偏移量
    private static final long SECONDARY;

    //初始化上面4个字段的值
    static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class<?> tk = Thread.class;
            parkBlockerOffset = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("parkBlocker"));
            SEED = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSeed"));
            PROBE = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomProbe"));
            SECONDARY = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
        } catch (Exception ex) { throw new Error(ex); }
    }

}

 

类 LockSupport

java.util.concurrent.locks.LockSupport extends Object

    用来创建锁和其他同步类的基本线程阻塞原语。

    此类以及每个使用它的线程与一个许可关联(从 Semaphore 类的意义上说)。如果该许可可用,并且可在进程中使用,则调用 park 将立即返回;否则可能 阻塞。如果许可尚不可用,则可以调用 unpark 使其可用。(但与 Semaphore 不同的是,许可不能累积,并且最多只能有一个许可。)

    park 和 unpark 方法提供了阻塞和解除阻塞线程的有效方法,并且不会遇到导致过时方法 Thread.suspend 和 Thread.resume 因为以下目的变得不可用的问题:由于许可的存在,调用 park 的线程和另一个试图将其 unpark 的线程之间的竞争将保持活性。此外,如果调用者线程被中断,并且支持超时,则 park 将返回。park 方法还可以在其他任何时间 “毫无理由” 地返回,因此通常必须在重新检查返回条件的循环里调用此方法。从这个意义上说,park 是 “忙碌等待” 的一种优化,它不会浪费这么多的时间进行自旋,但是必须将它与 unpark 配对使用才更高效。

    三种形式的 park 还各自支持一个 blocker 对象参数。此对象在线程受阻塞时被记录,以允许监视工具和诊断工具确定线程受阻塞的原因。(这样的工具可以使用方法 getBlocker(java.lang.Thread) 访问 blocker。)建议最好使用这些形式,而不是不带此参数的原始形式。在锁实现中提供的作为 blocker 的普通参数是 this

    这些方法被设计用来作为创建高级同步实用工具的工具,对于大多数并发控制应用程序而言,它们本身并不是很有用。park 方法仅设计用于以下形式的构造:

while (!canProceed()){
  ...
  LockSupport.park(this);
}

    在这里,在调用 park 之前, canProceed 和其他任何动作都不会锁定或阻塞。因为每个线程只与一个许可关联, park 的任何中间使用都可能干扰其预期效果。

    示例用法。 以下是一个先进先出 (first-in-first-out) 非重入锁类的框架。

class FIFOMutex {
   private final AtomicBoolean locked = new AtomicBoolean(false);
   private final Queue<Thread> waiters
     = new ConcurrentLinkedQueue<Thread>();

   public void lock() {
     boolean wasInterrupted = false;
     Thread current = Thread.currentThread();
     waiters.add(current);

     // Block while not first in queue or cannot acquire lock
     while (waiters.peek() != current ||
            !locked.compareAndSet(false, true)) {
        LockSupport.park(this);
        if (Thread.interrupted()) // ignore interrupts while waiting
          wasInterrupted = true;
     }

     waiters.remove();
     if (wasInterrupted)          // reassert interrupt status on exit
        current.interrupt();
   }

   public void unlock() {
     locked.set(false);
     LockSupport.unpark(waiters.peek());
   }
 }

    先进先出锁就是先申请锁的线程最先获得锁的资源,实现上采用了队列再加上 LockSupport.park。

  1. 将当前调用 lock 的线程加入队列
  2. 如果等待队列的队首元素不是当前线程或者 locked 为 true,则说明有线程已经持有了锁,那么调用 park 阻塞其余的线程。
  3. 如果队首元素是当前线程且 locked 为 false,则说明前面已经没有人持有锁,删除队首元素也就是当前的线程,然后当前线程继续正常执行。
  4. 执行完后调用 unlock 方法将锁变量修改为 false, 并解除队首线程的阻塞状态。此时的队首元素继续之前的判断。

 

方法摘要

static Object getBlocker(Thread t) 
          返回提供给最近一次尚未解除阻塞的 park 方法调用的 blocker 对象,如果该调用不受阻塞,则返回 null。
static void park() 
          为了线程调度,禁用当前线程,除非许可可用。
static void park(Object blocker) 
          为了线程调度,在许可可用之前禁用当前线程。
static void parkNanos(long nanos) 
          为了线程调度禁用当前线程,最多等待指定的等待时间,除非许可可用。
static void parkNanos(Object blocker, long nanos) 
          为了线程调度,在许可可用前禁用当前线程,并最多等待指定的等待时间。
static void parkUntil(long deadline) 
          为了线程调度,在指定的时限前禁用当前线程,除非许可可用。
static void parkUntil(Object blocker, long deadline) 
          为了线程调度,在指定的时限前禁用当前线程,除非许可可用。
static void unpark(Thread thread) 
          如果给定线程的许可尚不可用,则使其可用。

 

unpark

public static void unpark(Thread thread)

    如果给定线程的许可尚不可用,则使其可用。如果线程在 park 上受阻塞,则它将解除其阻塞状态。否则,保证下一次调用 park 不会受阻塞。如果给定线程尚未启动,则无法保证此操作有任何效果。

    参数:

    thread - 要执行 unpark 操作的线程;该参数为 null 表示此操作没有任何效果。

 

park

public static void park(Object blocker)

    为了线程调度,在许可可用之前禁用当前线程。

    如果许可可用,则使用该许可,并且该调用立即返回;否则,为线程调度禁用当前线程,并在发生以下三种情况之一前,使其处于休眠状态:

  • 其他某个线程调用将当前线程作为目标调用 unpark;或者
  • 其他某个线程中断当前线程;或者
  • 该调用不合逻辑地(即毫无理由地)返回。

    此方法不报告是哪个线程导致该方法返回。调用者应该重新检查最先导致线程暂停的条件。调用者还可以确定返回时该线程的中断状态。

    参数:

    blocker - 导致此线程暂停的同步对象

 

parkNanos

public static void parkNanos(Object blocker,long nanos)

    为了线程调度,在许可可用前禁用当前线程,并最多等待指定的等待时间。

    如果许可可用,则使用该许可,并且该调用立即返回;否则,为线程调度禁用当前线程,并在发生以下四种情况之一前,使其处于休眠状态:

  • 其他某个线程将当前线程作为目标调用 unpark;或者
  • 其他某个线程中断当前线程;或者
  • 已超过指定的等待时间;或者
  • 该调用不合逻辑地(即毫无理由地)返回。

    此方法不报告是哪个线程导致该方法返回。调用者应该重新检查最先导致线程暂停的条件。调用者还可以确定返回时该线程的中断状态或已过的时间。

参数:

    blocker - 导致此线程暂停的同步对象

    nanos - 要等待的最大毫秒数

 

parkUntil

public static void parkUntil(Object blocker, long deadline)

    为了线程调度,在指定的时限前禁用当前线程,除非许可可用。

    如果许可可用,则使用该许可,并且该调用立即返回;否则,为线程调度禁用当前线程,并在发生以下四种情况之一前,使其处于休眠状态:

  • 其他某个线程将当前线程作为目标调用 unpark;或者
  • 其他某个线程中断当前线程;或者
  • 指定时限已过;或者
  • 该调用不合逻辑地(即毫无理由地)返回。

    此方法不报告是哪个线程导致该方法返回。调用者应该重新检查最先导致线程暂停的条件。调用者还可以确定返回时该线程的中断状态或当前时间。

    参数:

    blocker - 导致此线程暂停的同步对象

    deadline - 要等待的绝对时间,用相对于历元 (Epoch) 的毫秒数值表示

 

getBlocker

public static Object getBlocker(Thread t)

    返回提供给最近一次尚未解除阻塞的 park 方法调用的 blocker 对象,如果该调用不受阻塞,则返回 null。返回的值只是一个瞬间快照,即由于未解除阻塞或者在不同的 blocker 对象上受阻而具有的线程。

 

park

public static void park()

    为了线程调度,禁用当前线程,除非许可可用。

    如果许可可用,则使用该许可,并且该调用立即返回;调用 park 后有以下三种情况,能使线程继续执行下去,否则就休眠:

  • 其他某个线程将当前线程作为目标调用 unpark;或者
  • 其他某个线程中断当前线程;或者
  • 该调用不合逻辑地(即毫无理由地)返回。

    此方法并不报告是哪个线程导致该方法返回。调用者应该重新检查最先导致线程暂停的条件。调用者还可以确定线程返回时的中断状态。

 

parkNanos

public static void parkNanos(long nanos)

    为了线程调度禁用当前线程,最多等待指定的等待时间,除非许可可用。

    如果许可可用,则使用该许可,并且该调用立即返回;否则,为线程调度禁用当前线程,并在发生以下四种情况之一以前,将其处于休眠状态:

  • 其他某个线程将当前线程作为目标调用 unpark;或者
  • 其他某个线程中断当前线程;或者
  • 已超过指定的等待时间;或者
  • 该调用不合逻辑地(即无缘无故地)返回。

    此方法并不报告是哪个线程导致该方法返回。调用者应该重新检查最先导致线程暂停的条件。调用者还可以确定线程返回时的中断状态或所用的时间。

    参数:

    nanos - 要等待的最大毫秒数

parkUntil

public static void parkUntil(long deadline)

    为了线程调度,在指定的时限前禁用当前线程,除非许可可用。

    如果许可可用,则使用该许可,并且调用立即返回;否则,为线程调度禁用当前线程,并在发生以下四种情况之一以前,将其处于休眠状态:

  • 其他某个线程将当前线程作为目标调用 unpark;或者
  • 其他某个线程中断当前线程;或者
  • 指定的最后期限已过;或者
  • 该调用不合逻辑地(即毫无理由地)返回。

    此方法并不报告是哪个线程导致该方法返回。调用者应该重新检查最先导致线程暂停的条件。调用者还可以确定线程返回时的中断状态或当前时间。

    参数:

    deadline - 要等待的绝对时间,用相对于历元的毫秒数值表示

AG 百家乐最新官网《 787977.tv 蝙蝠 14735340 》java 并发编程 (2):Java 多线程 - java.util.concurrent 高级工具

AG 百家乐最新官网《 787977.tv 蝙蝠 14735340 》java 并发编程 (2):Java 多线程 - java.util.concurrent 高级工具

高级多线程控制类

Java1.5 提供了一个非常高效实用的多线程包:java.util.concurrent, 提供了大量高级工具,可以帮助开发者编写高效、易维护、结构清晰的 Java 多线程程序。

ThreadLocal 类

ThreadLocal 类 用来保存线程的独立变量。对一个线程类(继承自 Thread)

当使用 ThreadLocal 维护变量时,ThreadLocal 为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。常用于用户登录控制,如记录 session 信息。

实现:每个 Thread 都持有一个 TreadLocalMap 类型的变量(该类是一个轻量级的 Map,功能与 map 一样,区别是桶里放的是 entry 而不是 entry 的链表。功能还是一个 map。)以本身为 key,以目标为 value。

主要方法是 get () 和 set (T a),set 之后在 map 里维护一个 threadLocal -> a,get 时将 a 返回。ThreadLocal 是一个特殊的容器。

原子类(AtomicInteger、AtomicBoolean……)

如果使用 atomic wrapper class 如 atomicInteger,或者使用自己保证原子的操作,则等同于 synchronized

AtomicInteger.compareAndSet (int expect,int update)// 返回值为 boolean

AtomicReference

对于 AtomicReference 来讲,也许对象会出现,属性丢失的情况,即 oldObject == current,但是 oldObject.getPropertyA != current.getPropertyA。

这时候,AtomicStampedReference 就派上用场了。这也是一个很常用的思路,即加上版本号

Lock 类 

lock: 在 java.util.concurrent 包内。共有三个实现:

  1. ReentrantLock
  2. ReentrantReadWriteLock.ReadLock
  3. ReentrantReadWriteLock.WriteLock

主要目的是和 synchronized 一样, 两者都是为了解决同步问题,处理资源争端而产生的技术。功能类似但有一些区别。

区别如下:

  1. lock 更灵活,可以自由定义多把锁的枷锁解锁顺序(synchronized 要按照先加的后解顺序)
  2. 提供多种加锁方案,lock 阻塞式,trylock 无阻塞式,lockInterruptily 可打断式, 还有 trylock 的带超时时间版本。
  3. 本质上和监视器锁(即 synchronized 是一样的)
  4. 能力越大,责任越大,必须控制好加锁和解锁,否则会导致灾难。
  5. 和 Condition 类的结合。
  6. 性能更高,synchronized 和 Lock 性能对比,如下图:
java.util.concurrent lock与synchronized 性能对比
java.util.concurrent lock 与 synchronized 性能对比

ReentrantLock 的使用

可重入的意义在于持有锁的线程可以继续持有,并且要释放对等的次数后才真正释放该锁。

private java.util.concurrent.locks.Lock lock = new ReentrantLock();
public void method() {	
	try {		
		lock.lock();		//获取到锁lock,同步块
	} finally {		
		lock.unlock();//释放锁lock
	}
}
复制
  • ReentrantLock 比 synchronized 功能更强大,主要体现:
  • ReentrantLock 具有公平策略的选择。
  • ReentrantLock 可以在获取锁的时候,可有条件性地获取,可以设置等待时间,很有效地避免死锁。
  • 如 tryLock () 和 tryLock (long timeout, TimeUnit unit)
  • ReentrantLock 可以获取锁的各种信息,用于监控锁的各种状态。
  • ReentrantLock 可以灵活实现多路通知,即 Condition 的运用。

公平锁与非公平锁

ReentrantLock 默认是非公平锁,允许线程 “抢占插队” 获取锁。公平锁则是线程依照请求的顺序获取锁,近似 FIFO 的策略方式。

锁的使用

  1. lock () 阻塞式地获取锁,只有在获取到锁后才处理 interrupt 信息
  2. lockInterruptibly () 阻塞式地获取锁,立即处理 interrupt 信息,并抛出异常
  3. tryLock () 尝试获取锁,不管成功失败,都立即返回 true、false,注意的是即使已将此锁设置为使用公平排序策略,tryLock () 仍然可以打开公平性去插队抢占。如果希望遵守此锁的公平设置,则使用 tryLock (0, TimeUnit.SECONDS),它几乎是等效的 (也检测中断)。
  4. tryLock (long timeout, TimeUnit unit) 在 timeout 时间内阻塞式地获取锁,成功返回 true,超时返回 false,同时立即处理 interrupt 信息,并抛出异常。

如果想使用一个允许闯入公平锁的定时 tryLock,那么可以将定时形式和不定时形式组合在一起:

if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }

private java.util.concurrent.locks.ReentrantLock lock = new ReentrantLock();
public void testMethod() {	
	try {		
		if (lock.tryLock(1, TimeUnit.SECONDS)) {
			//获取到锁lock,同步块
		} else {		
			//没有获取到锁lock
		}
	} catch (InterruptedException e) {
		e.printStackTrace();
	} finally {
		if (lock.isHeldByCurrentThread())
		//如果当前线程持有锁lock,则释放锁lock
			lock.unlock();
	}
}
复制

条件 Condition 的使用

条件 Condition 可以由锁 lock 来创建,实现多路通知的机制。

具有 await、signal、signalAll 的方法,与 wait/notify 类似,需要在获取锁后方能调用。

private final java.util.concurrent.locks.Lock lock = new ReentrantLock();
private final java.util.concurrent.locks.Condition condition = lock.newCondition();
public void await() {	
	try {		
		lock.lock();		//获取到锁lock
		condition.await();//等待condition通信信号,释放condition锁
		//接到condition通信
	} catch (InterruptedException e) {
		e.printStackTrace();
	} finally {
		lock.unlock();//释放对象锁lock
	}
}
复制

ReentrantReadWriteLock 的使用

ReentrantReadWriteLock 是对 ReentrantLock 更进一步的扩展,实现了读锁 readLock ()(共享锁) 和写锁 writeLock ()(独占锁),实现读写分离。读和读之间不会互斥,读和写、写和读、写和写之间才会互斥,提升了读写的性能。

读锁示例:

private final java.util.concurrent.locks.ReadWriteLock lock = new ReentrantReadWriteLock();
public void method() {	
	try {		
		lock.readLock().lock();//获取到读锁readLock,同步块
	} finally {		
		lock.readLock().unlock();//释放读锁readLock
	}
}
复制

写锁示例:

private final java.util.concurrent.locks.ReadWriteLock lock = new ReentrantReadWriteLock();
public void method() {	
	try {		
		lock.writeLock().lock(); //获取到写锁writeLock,同步块
	} finally {
		lock.writeLock().unlock(); //释放写锁writeLock
	}
}
复制

容器类

同步容器与异步容器概览

同步容器

包括两部分:

  • 一个是早期 JDK 的 Vector、Hashtable;
  • 一个是它们的同系容器,JDK1.2 加入的同步包装类,使用 Collections.synchronizedXxx 工厂方法创建。

Map<String, Integer> hashmapSync = Collections.synchronizedMap(new HashMap<>());

同步容器都是线程安全的,一次只有一个线程访问容器的状态

在某些场景下可能需要加锁来保护复合操作

复合类操作如:新增、删除、迭代、跳转以及条件运算。

这些复合操作在多线程并发的修改容器时,可能会表现出意外的行为,

最经典的便是 ConcurrentModificationException,

原因是当容器迭代的过程中,被并发的修改了内容,这是由于早期迭代器设计的时候并没有考虑并发修改的问题。

其底层的机制无非就是用传统的 synchronized 关键字对每个公用的方法都进行同步,使得每次只能有一个线程访问容器的状态。这很明显不满足我们今天互联网时代高并发的需求,在保证线程安全的同时,也必须有足够好的性能。

并发容器

与 Collections.synchronizedXxx () 同步容器等相比,util.concurrent 中引入的并发容器主要解决了两个问题:

  1. 根据具体场景进行设计,尽量避免 synchronized,提供并发性
  2. 定义了一些并发安全的复合操作,并且保证并发环境下的迭代操作不会出错

util.concurrent 中容器在迭代时,可以不封装在 synchronized 中,可以保证不抛异常,但是未必每次看到的都是 "最新的、当前的" 数据。

Map<String, Integer> concurrentHashMap = new ConcurrentHashMap<>();

ConcurrentHashMap 替代同步的 Map 即 (Collections.synchronized (new HashMap ()))。

众所周知,HashMap 是根据散列值分段存储的,同步 Map 在同步的时候会锁住整个 Map,而 ConcurrentHashMap 在设计存储的时候引入了段落 Segment 定义,同步的时候只需要锁住根据散列值锁住了散列值所在的段落即可,大幅度提升了性能。ConcurrentHashMap 也增加了对常用复合操作的支持,比如 "若没有则添加":putIfAbsent (),替换:replace ()。这 2 个操作都是原子操作。注意的是 ConcurrentHashMap 弱化了 size () 和 isEmpty () 方法,并发情况尽量少用,避免导致可能的加锁 (当然也可能不加锁获得值,如果 map 数量没有变化的话)。 CopyOnWriteArrayList 和 CopyOnWriteArraySet 分别代替 List 和 Set,主要是在遍历操作为主的情况下来代替同步的 List 和同步的 Set,这也就是上面所述的思路:迭代过程要保证不出错,除了加锁,另外一种方法就是 "克隆" 容器对象。--- 缺点也明显,占有内存,且数据最终一致,但数据实时不一定一致,一般用于读多写少的并发场景。

  • ConcurrentSkipListMap 可以在高效并发中替代 SoredMap (例如用 Collections.synchronzedMap 包装的 TreeMap)。
  • ConcurrentSkipListSet 可以在高效并发中替代 SoredSet (例如用 Collections.synchronzedSet 包装的 TreeMap)。
  • ConcurrentLinkedQuerue 是一个先进先出的队列。它是非阻塞队列。注意尽量用 isEmpty,而不是 size ();

CountDownLatch 闭锁的使用

管理类

管理类的概念比较泛,用于管理线程,本身不是多线程的,但提供了一些机制来利用上述的工具做一些封装。

了解到的值得一提的管理类:ThreadPoolExecutor 和 JMX 框架下的系统级管理类 ThreadMXBean

ThreadPoolExecutor

如果不了解这个类,应该了解前面提到的 ExecutorService,开一个自己的线程池非常方便:

ExecutorService e = Executors.newCachedThreadPool();
    ExecutorService e = Executors.newSingleThreadExecutor();
    ExecutorService e = Executors.newFixedThreadPool(3);
    // 第一种是可变大小线程池,按照任务数来分配线程,
    // 第二种是单线程池,相当于FixedThreadPool(1)
    // 第三种是固定大小线程池。
    // 然后运行
    e.execute(new MyRunnableImpl());
复制

该类内部是通过 ThreadPoolExecutor 实现的,掌握该类有助于理解线程池的管理,本质上,他们都是 ThreadPoolExecutor 类的各种实现版本。

参考文章:

Java 多线程并发编程一览笔录 https://www.cnblogs.com/yw0219/p/10597041.html

Java 中的多线程你只要看这一篇就够了 https://juejin.im/entry/57339fe82e958a0066bf284f

Android-Studio-2.3错误:java.util.concurrent.ExecutionException:java.lang.RuntimeException:AAPT进程尚未准备好接收命令

Android-Studio-2.3错误:java.util.concurrent.ExecutionException:java.lang.RuntimeException:AAPT进程尚未准备好接收命令

大家好,我是 Android-Studio-2.3的新手

我弹出这些错误消息:
错误:java.util.concurrent.ExecutionException:java.lang.RuntimeException:AAPT进程尚未准备好接收命令

错误:任务’:app:mergeDebugResources’的执行失败.

Error: java.util.concurrent.ExecutionException: java.lang.RuntimeException: AAPT process not ready to receive commands

我去过很多网站,但我找不到解决这个问题的办法
顺便说一句,我已经尝试将我的gradle降级到23.0.0或23.0.1,但它仍然无效. Android-Studio要求我下载25.0.0版本但是当我这样做时,上面的错误消息仍然出现!

有没有人有解决方案,我会非常感激:)

解决方法

我有同样的问题,也没有解决它.但:
我假设你试图在Ubuntu上安装android studio?如果我是对的,你可以查看你有哪个操作系统.如果它是64位操作系统,您可以尝试使用以下内容:
sudo apt-get install lib32stdc++6
sudo apt-get install lib32z1

也许有帮助.

com.intellij.util.ReflectionUtil 对方法 java.util.ResourceBundle.setParent(java.util.ResourceBundle) 的非法反射访问

com.intellij.util.ReflectionUtil 对方法 java.util.ResourceBundle.setParent(java.util.ResourceBundle) 的非法反射访问

如何解决com.intellij.util.ReflectionUtil 对方法 java.util.ResourceBundle.setParent(java.util.ResourceBundle) 的非法反射访问

我在 VSCode 中编写了一些 kotlin 代码

其中之一是:

public void readCSV(String fileName) {
    fileLocation = fileName;
    File csvFile = new File(fileName);
    Scanner sfile;
//    noOfColumns = 0;
//    noOfRows = 0;
    data = new ArrayList<ArrayList>();
    int colCounter = 0;
    int rowCounter = 0;
    
    try {
        sfile = new Scanner(csvFile);
        
        while (sfile.hasNextLine()) {
            String aLine = sfile.nextLine();
            Scanner sline = new Scanner(aLine);
            sline.useDelimiter(",");
            colCounter = 0;
            while (sline.hasNext()) {
                if (rowCounter == 0) 
                    data.add(new ArrayList<String>());
                
                
                data.get(colCounter).add(sline.next());
                colCounter++;
            }
            rowCounter++;
            sline.close();
        }
//        noOfColumns = colCounter;
//        noOfRows = rowCounter;
        sfile.close();
    } catch (FileNotFoundException e) {
        System.out.println("File to read " + csvFile + " not found!");
    }
} 

当我运行它时,我得到:

fun main() {
println("Hello world")
}

它有效,但我无法隐藏或修复警告,我使用 JDK 15

我在 IntelliJ 上没有收到这些警告

CompletableFuture 源码详解之 java.util.concurrent.CompletableFuture#supplyAsync (java.util.function.Suppl...

CompletableFuture 源码详解之 java.util.concurrent.CompletableFuture#supplyAsync (java.util.function.Suppl...

/**
     * Returns a new CompletableFuture that is asynchronously completed
     * by a task running in the {@link ForkJoinPool#commonPool()} with
     * the value obtained by calling the given Supplier.
     *
     * @param supplier a function returning the value to be used
     * to complete the returned CompletableFuture
     * @param <U> the function''s return type
     * @return the new CompletableFuture
     */
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
        return asyncSupplyStage(asyncPool, supplier);
    }

  CompletableFuture 下的 supplyAsync 方法是一个执行异步任务且有返回结果的任务,使用例子如下:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * 测试类
 * @author yangchangkui
 */
public class TestMy {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        long start = System.currentTimeMillis();
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello";
        });
        //判断是否已经完成
        System.out.println("耗时:"+(System.currentTimeMillis()-start)+",isDone:"+completableFuture.isDone());
        //阻塞获取结果
        String result = completableFuture.get();
        System.out.println("耗时:"+(System.currentTimeMillis()-start)+",result:"+result);
        //判断是否已经完成
        System.out.println("耗时:"+(System.currentTimeMillis()-start)+",isDone:"+completableFuture.isDone());

    }
}

  执行结果如下,显然,达到了异步执行的效果,比如在一些调用很多外部接口的聚合接口,只要接口不作为入参,那就可以进行异步执行,最后阻塞拿结果,提高接口的 QPS,提高系统性能。

 

关于java.util.concurrent.locks.LockSupport 源码java.util.scanner源码的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于AG 百家乐最新官网《 787977.tv 蝙蝠 14735340 》java 并发编程 (2):Java 多线程 - java.util.concurrent 高级工具、Android-Studio-2.3错误:java.util.concurrent.ExecutionException:java.lang.RuntimeException:AAPT进程尚未准备好接收命令、com.intellij.util.ReflectionUtil 对方法 java.util.ResourceBundle.setParent(java.util.ResourceBundle) 的非法反射访问、CompletableFuture 源码详解之 java.util.concurrent.CompletableFuture#supplyAsync (java.util.function.Suppl...的相关知识,请在本站寻找。

本文标签: