Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列

这篇具有很好参考价值的文章主要介绍了Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

JUC是什么?

JUC是java.util.concurrent包的简称,在Java5.0添加,目的就是为了更好的支持高并发任务。让开发者进行多线程编程时减少竞争条件和死锁的问题


Java中线程有六个状态

java.lang.Thread.State

public enum State {
       // 新生
        NEW,

        // 运行
        RUNNABLE,

        // 阻塞
        BLOCKED,

        // 等待
        WAITING,

        //超时等待
        TIMED_WAITING,

        //终止
        TERMINATED;
    }

JUC的结构 

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言

tools(工具类):又叫信号量三组工具类,包含有

CountDownLatch(闭锁) 是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待

CyclicBarrier(栅栏) 之所以叫barrier,是因为是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 ,并且在释放等待线程后可以重用。

Semaphore(信号量) 是一个计数信号量,它的本质是一个“共享锁“。信号量维护了一个信号量许可集。线程可以通过调用 acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。

executor(执行者):是Java里面线程池的顶级接口,但它只是一个执行线程的工具,真正的线程池接口是ExecutorService,里面包含的类有:

ScheduledExecutorService 解决那些需要任务重复执行的问题

ScheduledThreadPoolExecutor 周期性任务调度的类实现

atomic(原子性包):是JDK提供的一组原子操作类

包含有AtomicBoolean、AtomicInteger、AtomicIntegerArray等原子变量类,他们的实现原理大多是持有它们各自的对应的类型变量value,而且被volatile关键字修饰了。这样来保证每次一个线程要使用它都会拿到最新的值。

locks(锁包):是JDK提供的锁机制,相比synchronized关键字来进行同步锁,功能更加强大,它为锁提供了一个框架,该框架允许更灵活地使用锁包含的实现类有:

ReentrantLock 它是独占锁,是指只能被独自占领,即同一个时间点只能被一个线程锁获取到的锁。

ReentrantReadWriteLock 它包括子类ReadLock和WriteLock。ReadLock是共享锁,而WriteLock是独占锁。

LockSupport 它具备阻塞线程和解除阻塞线程的功能,并且不会引发死锁。

collections(集合类):主要是提供线程安全的集合, 比如:

ArrayList对应的高并发类是CopyOnWriteArrayList,

HashSet对应的高并发类是 CopyOnWriteArraySet,

HashMap对应的高并发类是ConcurrentHashMap等等


synchronized和JUC的Lock

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言

synchronized和lock锁的区别

synchronized内置的java关键字,Lock是一个java类
synchronized无法判断获取锁的状态, Lock可以判断是否获取到了锁
synchronized会自动释放锁,Lock必须要手动释放锁!如果不是释放锁,会产生死锁
synchronized 线程1(获得锁,阻塞),线程2(等待); Lock锁就不一定会等待下去
synchronized 可重入锁,不可以中断的,非公平的; Lock锁,可重入的,可以判断锁,非公平(可自己设置);
synchronized 适合锁少量的代码同步问题,Lock 适合锁大量的同步代码


reentrantLock

ReentrantLock 和 synchronized 的区别:

🍃1.synchronized 使用时不需要手动释放锁. ReentrantLock 使用时需要手动释放. 使用起来更灵活, 但是也容易遗漏 unlock。

🍃2.synchronized只是非公平锁,ReentranLock 提供了公平锁和非公平锁两种实现,可以通过构造方法来切换。

🍃3.ReentrantLock 还提供了一个特殊的加锁操作-- tryLock()。默认的 lock() 加锁失败就阻塞,而 tryLock() 加锁失败,则不阻塞,继续往下执行,并且返回 false。除了立即失败之外,tryLock() 还能设定一定的等待时间。

🍃4.ReentrantLock 提供了更强大的等待/唤醒 机制。 synchronized 搭配的是 Object 类的 wait,notify,只能随机唤醒其中一个线程;ReentrantLock 搭配了 Condition 类来实现等待唤醒,可以做到能随机唤醒一个,也能指定线程唤醒。

构造方法:

  	public ReentrantLock() {
        sync = new NonfairSync(); //无参默认非公平锁
    }
 	public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();//传参为true为公平锁
    }
 
public class SaleTicketDemo {

    public static void main(String[] args) {
        Ticket ticket = new Ticket();

        new Thread(()->{for(int i = 0; i < 40; i++) ticket.sale();}, "a").start();
        new Thread(()->{for(int i = 0; i < 40; i++) ticket.sale();}, "b").start();
        new Thread(()->{for(int i = 0; i < 40; i++) ticket.sale();}, "c").start();

    }
}

class Ticket {

    private int ticketNum = 30;
    private Lock lock = new ReentrantLock();

    public void sale() {
        lock.lock();
        try {
            if (this.ticketNum > 0) {
                System.out.println(Thread.currentThread().getName() + "购得第" + ticketNum-- + "张票, 剩余" + ticketNum + "张票");
            }
            //增加错误的发生几率
            Thread.sleep(10);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}


Condition

精准的通知和唤醒线程
Condition是个接口,基本的方法就是await()和signal()方法;
Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用
Conditon中的await()对应Object的wait();

Condition中的signal()对应Object的notify();

Condition中的signalAll()对应Object的notifyAll()。

对比项 Object Monitor Methods Condition
前置条件 获取对象的锁 调用Lock.lock()获取锁
调用Lock.newCondition() 获取 Condition 对象
调用方式 直接调用
如:object.wait0
直接调用
如:condition.await()
等待队列个数 一个 多个
当前线程释放锁并进入等待状态 支持 支持
当前线程释放锁并进入等待状态,在
等待状态中不响应中断
不支持 支持
当前线程释放锁并进入超时等待状态 支持 支持
当前线程释放锁并进入等待状态到将
来的某个时间
不支持 支持
唤醒等待队列中的一个线程 支持 支持
唤醒等持队列中的全部线程 支持

 Condition常见例子(生产者消费者模式)

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class PC {
    public static void main(String[] args) {
        a a = new a();
        new Thread(()->{
            for (int i =0;i<10;i++){
                a.increment();
            }
        },"A").start();
        new Thread(()->{
            for (int i =0;i<10;i++){
                a.decrease();
            }
        },"B").start();


    }

}
class  a{
    public int nummber=0;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    public   void  increment(){
        lock.lock();
        try {
            while(nummber!=0){
                condition.await();
            }
            nummber++;
            System.out.println(Thread.currentThread().getName()+">>"+nummber);
            condition.signalAll();
        }
         catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
          lock.unlock();
        }

    }
    public  void decrease(){
        lock.lock();
        try {
            while(nummber!=1){
                condition.await();
            }
            nummber--;
            System.out.println(Thread.currentThread().getName()+">>"+nummber);
            condition.signalAll();
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}



JUC下的读写锁ReentrantReadWriteLock

ReadWriteLock

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言

package com.czp.lock;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;


/**
 * 独占锁(写锁) 一次只能由一个线程占有
 * 共享锁(读锁) 一次可以有多个线程占有
 * readWriteLock
 * 读-读 可以共存
 * 读-写  不能共存
 * 写-写 不能共存
 */
public class ReadWriteLock {

    public static void main(String[] args) {
        MyCacheLock myCache = new MyCacheLock();

        //写入操作
        for (int i = 0; i < 6; i++) {
            int temp = i;
            new Thread(() -> {
                myCache.put(temp + "", temp + "");
            }, String.valueOf(i)).start();
        }

        //读取操作
        for (int i = 0; i < 6; i++) {
            int temp = i;
            new Thread(() -> {
                myCache.get(temp + "");
            }, String.valueOf(i)).start();
        }
    }
}

class MyCacheLock {

    private volatile Map<String, Object> map = new HashMap<>();
    //读写锁
    private java.util.concurrent.locks.ReadWriteLock lock = new ReentrantReadWriteLock();

    // 存,写入的时候只有一个人操作
    public Object get(String key) {
        lock.readLock().lock();
        Object o = null;
        try {
            System.out.println(Thread.currentThread().getName() + "读取");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            o = map.get(key);
            System.out.println(Thread.currentThread().getName() + "读取ok" + o);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.readLock().unlock();
        }
        return o;
    }

    public void put(String key, Object value) {
        lock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "写入" + key);
            map.put(key, value);
            System.out.println(Thread.currentThread().getName() + "写入完毕");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.writeLock().unlock();
        }
    }

}

class MyCache {

    private volatile Map<String, Object> map = new HashMap<>();

    public Object get(String key) {
        System.out.println(Thread.currentThread().getName() + "读取");

        Object o = map.get(key);
        System.out.println(Thread.currentThread().getName() + "读取ok" + o);

        return o;
    }

    public void put(String key, Object value) {
        System.out.println(Thread.currentThread().getName() + "写入" + key);
        map.put(key, value);
        System.out.println(Thread.currentThread().getName() + "写入完毕");
    }

}


不安全的集合类和JUC的collections

list 不安全-CpoyOnWriteArrayList

CpoyOnWriteArrayList(写时复制)。当多个线程读的时候,是线程安全的,不需要加锁;当多个线程涉及到修改的时候,先将当前容器进行Copy, 复制出一个新的容器,然后新的容器里添加元素, 添加完元素之后,再将原容器的引用指向新的容器。

//java.util.ConcurrentModificationException 并发修改异常!
public class ListTest {

    public static void main(String[] args) {
        //并发下 arrayList 是不安全的
        /**
         * 解决方案
         * 1. 使用vector解决
         * 2. List<String> arrayList = Collections.synchronizedList(new ArrayList<>());
         * 3. List<String> arrayList = new CopyOnWriteArrayList<>();
         */
        //copyOnWrite 写入时复制  COW 计算机程序设计领域的一种优化策略
        //多个线程调用的时候, list, 读取的时候固定的,写入的时候,可能会覆盖
        //在写入的时候避免覆盖造成数据问题
        //CopyOnWriteArrayList 比 vector牛逼在哪里

        //读写分离
        List<String> arrayList = new CopyOnWriteArrayList<>();
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                arrayList.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(arrayList);
            },String.valueOf(i)).start();
        }
    }
}



set 不安全-CopyOnWriteArraySet

/**
 * 同理可证
 */
public class SetTest {

    public static void main(String[] args) {

//        Set<String> set = new HashSet<>();
        //如何解决hashSet线程安全问题
        //1. Set<String> set = Collections.synchronizedSet(new HashSet<>());
        Set<String> set = new CopyOnWriteArraySet<>();

        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                set.add(UUID.randomUUID().toString().substring(0, 5));
                System.out.println(set);
            }, String.valueOf(i)).start();
        }
    }
}

hashSet底层是hashMap

public HashSet() {
    map = new HashMap<>();
}

// add 的本质就是 map 的 key key是无法重复的
public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}
private static final Object PRESENT = new Object();//这是一个不变的值


HashMap不安全-ConcurrentHashMap

Hashtable 是线程安全的,但是不推荐使用,因为它的做法是直接给 Hashtable 对象本身加锁。

如果是 Hashtable 这种加锁方式,两线程访问不同链表中的元素(hash运算不等会放在不同链表中),不会产生线程安全的情况,它也给加锁了,这就导致严重的竞争关系,大大的拖慢了程序的效率!!

size 属性也是通过 synchronized 来控制同步 , 也是比较慢的。
一旦触发扩容 , 就由该线程完成整个扩容过程 . 这个过程会涉及到大量的元素拷贝 , 效率会非常低。

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言

ConcurrentHashMap

ConcurrentHashMap 相比于 Hashtable 做出了重大改进,它把锁的粒度细化了。(下图的改进是基于 Java 8 的)

此时每个桶一把锁,访问不同链表的元素,就不会产生锁竞争了;并且一个哈希表上面的桶的个数可能会非常多,这就进一步使锁冲突的概率大大降低了(稀释了)。

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言

总结 ConcurrentHashMap 的优化策略 :

把锁的粒度细化了,给每个哈希桶都加上一把锁(链表的头结点),降低了锁冲突的概率。

读不加锁,写才加锁。

读操作没有加锁,目的是为了进一步降低锁冲突的概率。为了保证读到刚修改的数据, 搭配了

volatile 关键字。 

在维护 size 的时候,使用 CAS 机制,又进一步降低了锁冲突。

针对扩容场景做出了优化:化整为零

发现需要扩容的线程,只需要创建一个新的数组,同时只搬几个元素过去。扩容期间,新旧数组同时存在。后续每个来操作 ConcurrentHashMap 的线程, 都会参与搬家的过程,每个操作负责搬运一小部分元素。搬完最后一个元素再把旧数组删掉。这个期间,插入只往新数组加增加,查找需要同时查新数组和旧数组。
而 Hashtable,HashMap 它们在某次 put 的时候,触发扩容,由这个 put 完成整个扩容操作,就巨慢无比,非常低效!!

在 Java 8 之前,此处的 ConcurrentHashMap 并不是每个桶加锁,而是"分段锁",若干个桶一把锁,类似下图:

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言

HashMap 中 key 允许为 null ,Hashtable 和 ConcurrentHashMap 不允许


JUC的Callable()创建线程

普通的线程代码, 之前都是用的thread或者runnable接口

public class demo01 {
    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        threadDemo.start();
        new Thread(new ThreadDemo2()).start();
    }
}

class ThreadDemo extends Thread{
    @Override
    public void run() {
        System.out.println("普通线程已开启(继承Thread)");
    }
}
class ThreadDemo2 implements Runnable{

    @Override
    public void run() {
        System.out.println("普通线程已开启(实现Runnable接口)");
    }
}

使用FutureTask+Callable创建多线程的方式

  1. 可以有返回值
  2. 可以抛出异常
  3. 方法不同, run() => call()

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言

public class CallableTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask = new FutureTask<>(new MyThread());
        new Thread(futureTask,"a").start();
        System.out.println(futureTask.get());

    }
}

class MyThread implements Callable<Integer> {


    @Override
    public Integer call() throws Exception {
        System.out.println("call()方法被调用了");
        return 1024;
    }
}



JUC中的tools(工具类/辅助类)

CountDownLatch

countDownLatch.countDown(); //数量减1

countDownLatch.await();// 等待计数器归零,然后再向下执行

每次有线程调用countDown()数量-1,假设计数器变为0,countDownLatch.await();就会被唤醒,继续执行

//计数器
public class demo02 {
    public static void main(String[] args) throws InterruptedException {
        //相当于计数器
        CountDownLatch countDownLatch = new CountDownLatch(5);
        //计数器总数是5,当减少为0,任务才继续向下执行
        for (int i = 1; i <6 ; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"==>start");
                countDownLatch.countDown();
            }).start();
        }
        countDownLatch.await();
        System.out.println("main线程继续向下执行");
    }
}

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言


cyclicBarrier

public class CyclicBarrierDemo {

    public static void main(String[] args) {
        /**
         * 集齐77个龙珠召唤神龙
         */
        // 召唤龙珠的线程
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, ()->{
            System.out.println("召唤神龙成功! ");
        });
        for (int i = 0; i < 7; i++) {
            int temp = i;
            //lambda 能拿到i吗
            new Thread(()->{
                System.out.println(Thread.currentThread().getName() + "收集" + temp + "个龙珠");


                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言


Semaphore

semaphore.acquire(); //获取信号量,假设如果已经满了,等待信号量可用时被唤醒

semaphore.release(); //释放信号量

作用: 多个共享资源互斥的使用!并发限流,控制最大的线程数

public class SemaphoreTest {

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);

        for (int i = 0; i < 6; i++) {
            int temp = i;
            new Thread(()->{
                try {
                    semaphore.acquire(); //获取
                    System.out.println(temp + "号车抢到车位");
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release(); //释放
                    System.out.println(temp + "号车离开车位");
                }
            }).start();
        }
    }
}


JUC下的阻塞队列

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言

什么情况下我们会使用阻塞队列,多线程并发处理,线程池!
如何使用队列?
添加 移除
四组API,核心put()、take()

方式 抛出异常 不会抛出异常,有返回值 阻塞等待 超时等待
添加操作 add() offer()供应 put() offer(obj,int,timeunit.status)
移除操作 remove() poll()获得 take() poll(int,timeunit.status)
判断队列首部 element() peek()偷看,偷窥

   /**
     * 抛出异常
     */
    public static void test1() {
        //队列的大小
        ArrayBlockingQueue queue = new ArrayBlockingQueue<>(3);
        System.out.println(queue.add("a"));
        System.out.println(queue.add("b"));
        System.out.println(queue.add("c"));
        //java.lang.IllegalStateException: Queue full
        //System.out.println(queue.add("d"));
        System.out.println("----------------------");
        System.out.println(queue.remove());
        System.out.println(queue.remove());
        System.out.println(queue.remove());
        //java.util.NoSuchElementException
        System.out.println(queue.remove());
        //抛出异常

    }

   /**
     * 有返回值没有异常
     */
    public static void test2(){
        ArrayBlockingQueue queue = new ArrayBlockingQueue(3);

        System.out.println(queue.offer("a"));
        System.out.println(queue.offer("b"));
        System.out.println(queue.offer("c"));
//        System.out.println(queue.offer("d"));       //offer 不抛出异常
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
//        System.out.println(queue.poll());   //null 不抛出异常
    }

    /**
     * 等待阻塞
     */
    public static void test3() throws InterruptedException {
        ArrayBlockingQueue queue = new ArrayBlockingQueue(3);
        queue.put("a");
        queue.put("b");
        queue.put("c");
//        queue.put("c");  队列没有位置就会阻塞
        System.out.println(queue.take());
        System.out.println(queue.take());
        System.out.println(queue.take());
    }

SynchronousQueue同步队列
没有容量,
进去一个元素,必须等待取出来之后,才能再往里面放一个元素
put take


/**
 * 同步队列
 * 和其他的lockQueue 不一样, SynchronousQueue 不存储元素
 */
public class SyncQueue {

    public static void main(String[] args) {
        SynchronousQueue<String> synchronousQueue = new SynchronousQueue<>(); //同步队列

        new Thread(()->{

            try {
                System.out.println(Thread.currentThread().getName() + "put 1");
                synchronousQueue.put("1");
                System.out.println(Thread.currentThread().getName() + "put 2");
                synchronousQueue.put("2");
                System.out.println(Thread.currentThread().getName() + "put 3");
                synchronousQueue.put("3");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"T1").start();

        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName() + "=>" + synchronousQueue.take());
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName() + "=>" + synchronousQueue.take());
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName() + "=>" + synchronousQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
            }
        },"T2").start();
    }
}

运行结果

T1put 1
T2=>1
T1put 2
T2=>2
T1put 3
T2=>3


JUC下的类构建线程池

Executors

静态静态工厂方法,最终都是通过ThreadPoolExecutor类来完成的

Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言 Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列,Java,java,开发语言文章来源地址https://www.toymoban.com/news/detail-753583.html

到了这里,关于Java - JUC(java.util.concurrent)包详解,其下的锁、安全集合类、线程池相关、线程创建相关和线程辅助类、阻塞队列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何解决java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@7566d7cf r...

    Java中的 java.util.concurrent.RejectedExecutionException 异常表示无法将任务提交到线程池中执行。这通常是因为线程池处于关闭状态或者已经达到了最大线程数,无法再接受新的任务。 要解决这个异常,你可以考虑以下几种方法: 检查线程池的状态,确保它处于可以接受新任务的状态

    2024年02月13日
    浏览(41)
  • java.util.concurrent.Executionexception 异常

    今天运行时发生了如下报错。自己捣鼓半天也没发现问题出在哪儿,感谢大佬的帮助,记录下来防止再犯。。 caused by org.apache.flink.client.program.programInvocationException: Job failed。程序调用异常。网上找了很多解决方法,都没有能够解决这个问题。 直到在报错中发现了这一行: C

    2024年02月19日
    浏览(27)
  • 已解决java.util.concurrent.ExecutionException异常的正确解决方法,亲测有效!!!

    已解决java.util.concurrent.ExecutionException异常的正确解决方法,亲测有效!!! java.util.concurrent.ExecutionException java.util.concurrent.ExecutionException是Java多线程编程中常见的异常之一,它表示在执行一个Callable或者Runnable任务时,任务抛出了一个异常。 下滑查看解决方法 具体解决方法可

    2024年02月11日
    浏览(22)
  • 关于报错java.lang.reflect.InaccessibleObjectException: Unable to make field private java.util.concurrent

    java.lang.reflect.InaccessibleObjectException: Unable to make field private java.util.concurrent.Callable java.util.concurrent.FutureTask.callable accessible: module java.base does not \\\"opens java.util.concurrent\\\" to unnamed module @32eebfca 假如报这种错误,只需要在Run-Edit Configurations-Modify Options-add VM options中加  假如你报的是下面

    2024年02月15日
    浏览(51)
  • 【问题已解决】Unrecognized option: --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED

    今天在创建java项目时,运行报错,说无法成功创建java程序。 Unrecognized option: --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit. 解决办法: 1、使用最新的jdk版本 2、在第三处,选择最新的jdk版本

    2024年02月13日
    浏览(34)
  • idea启动报错Internal error. Please refer to https://jb.gg/ide/critical-startup-errors java.util.concurr

    java.util.concurrent.CompletionException: org.picocontainer.PicoRegistrationException: Key com.tang.intellij.lua.luacheck.LuaCheckSettings duplicated) Internal error. Please refer to https://jb.gg/ide/critical-startup-errors java.util.concurrent.CompletionException: org.picocontainer.PicoRegistrationException: Key com.tang.intellij.lua.luacheck.LuaCheckSetti

    2023年04月17日
    浏览(54)
  • 字节跳动大厂面试题详解:java中有哪些类型的锁

    作者简介 :一名后端开发人员,每天分享后端开发以及人工智能相关技术,行业前沿信息,面试宝典。 座右铭 :未来是不可确定的,慢慢来是最快的。 个人主页 :极客李华-CSDN博客 合作方式 :私聊+ 这个专栏内容 :BAT等大厂常见后端java开发面试题详细讲解,更新数目10

    2024年02月21日
    浏览(30)
  • Java开发 - 不知道算不算详细的JUC详解

    大概有快两周没有发文了,这段时间不断的充实自己,算算时间,也到了该收获的时候,今天带来一篇JUC详解,但说实话,我也不敢自信它详不详细。JUC说白了就是多线程,学Java不久的人知道多线程,恐怕还不知道JUC是什么。在这篇博客中,博主将对JUC做一个自认为比较全面

    2024年02月06日
    浏览(29)
  • Java性能测试中常用的锁

    多线程编程在现代软件开发中扮演着至关重要的角色。它使我们能够有效地利用多核处理器和提高应用程序的性能。然而,多线程编程也伴随着一系列挑战,其中最重要的之一就是处理共享资源的线程安全性。在这个领域,锁(Lock)是一个关键的概念,用于协调线程之间对共

    2024年01月16日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包