JUC初步理解(二)

CopyOnWriteArrayList
When

CopyOnWriteArrayList是jdk1.5以后并发包提供的一种并发容器,写操作通过创建底层的数组的新副本实现,是一种读写分离的并发策略,被我们称为“写时复制容器”,类似的还有CopyOnWriteArraySet

Way

集合框架ArrayList是线程不安全的,vector虽然是线程安全的,但处理方式简单粗暴synchronized,性能差,而CopyOnWriteArrayList提供了不同的的处理并发思路

How

很多时候,我们的系统中处理的都是读多写少的并发场景,CopyOnWriteArrayList允许并发的读,读操作是无锁的,性能比较高,写操作的话,比如向容器内增加一个元素,首先将当前容器复制一份,然后在新副本进行操作,结束之后将原容器的引用接向新容器

优缺点分析
优点:

读操作性能很高,因为无需同步操作,比较适合读多写少的并发情况

缺点:

一是内存占用问题,因为写操作都要复制
二是无法保证实时性,在写操作的时候,读操作是不会发生阻塞的,未切换到新容器,读操作无法读到最新的内容

Callable

Callable和Runable都代表着任务,区别于Runable在与有返回值并且可以抛异常
Callable的call()方法类似Runable中的run方法,都定义要完成的工作,实现这两个接口时分别要重写这2个方法,主要的不同之处在call()有返回值,运行callable任务可以拿到一个future对象,表示异步计算的结果,它提供检测计算是否完成的方法,以等待计算的完成,并检索计算的结果,通过Future对象可以了解任务执行的情况,可取消任务的执行,还可以获取执行的结果

Callable类型的任务可以有两种执行方式

借助FutureTask
package com.boom.example.demo.aa;

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

public class CallableAndFutureTask {
    public static void main(String[] args) {
        Callable<Integer> objectCallable = new Callable<>(){

            @Override
            public Integer call() throws Exception {
                return new Random().nextInt(100);
            }
        };
        FutureTask<Integer> integerFutureTask = new FutureTask<Integer>(objectCallable);

        new Thread(integerFutureTask).start();
        try {
            Thread.sleep(5000);
            System.out.println(integerFutureTask.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Callable任务和线程池一起使用,然后返回值是Future:
package com.boom.example.demo.aa;

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class CallableAndFuture {
    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<Integer> submit = executorService.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return new Random().nextInt(10);
            }
        });
        Thread.sleep(5000);
        System.out.println(submit.get());
        executorService.shutdown();

    }
}

当执行多个Callable任务,有多个返回值时,我们可以创建一个Future的集合,例如:

package com.boom.example.demo.aa;
import java.util.ArrayList;
import java.util.concurrent.*;

class MyCallableTask implements Callable<String>{
    private int id;

    public MyCallableTask(int id) {
        this.id = id;
    }

    @Override
    public String call() throws Exception {
        for(int i = 1;i<=5;i++){
            System.out.println("Thead" + id);
        }
        return "resuit  " + id;
    }
}
public class  Callabletest {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        ArrayList<Future<String>> futures = new ArrayList<Future<String>>();
        for(int i=1;i<=5;i++){
            futures.add(executorService.submit(new MyCallableTask(i)));
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for(Future<String> fu:futures){
            //运行完成返回true
            if(fu.isDone()) {
                try {
                    System.out.println(fu.get());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }else{
                System.out.println("MyCallableTask任务未完成!");
            }
        }
        executorService.shutdown();
    }
}

CountDownLatch(倒计时计算器)

是一个工具类,起到线程之间通信的作用

package com.boom.example.demo.aa;

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for(int i = 1;i <=5;i++){
            new Thread(()->{
                System.out.println(Thread.currentThread().getName());
                countDownLatch.countDown();
            },String.valueOf(i)).start();

        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("mian");

    }
}

CyclicBarrier(加法计算器)

是一个同步的辅助类,允许一组线程相互之间等待,达到一个共同点,再继续执行

Semaphore

也是线程同步辅助类,可维护当前线程个数,并提供同步机制

package com.boom.example.demo.aa;

import java.util.concurrent.Semaphore;

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

        for(int i=1;i<=6;i++){
            new Thread(()->{
                try {
                    semaphore.acquire();//获取一个线程许可
                    System.out.println(Thread.currentThread().getName());
                    System.out.println("进入车库");
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName());
                    System.out.println("离开车库");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();//释放许可
                }
            },String.valueOf(i)).start();
        }

    }
}

ReadWriteLock

Synchronized和ReentrantLock都是排他锁,同一时刻只允许一个线程访问共享资源,在平时场景会经常遇到读多写少的场景,在这种场景下,每次只允许一个线程访问,效率比较低下
读写锁就因运而生了,它由读锁和写锁两部分组成,读写锁的特点:同一时刻允许多个线程对共享资源进行读操作,同一时刻只允许一个线程对共享资源进行写操作,当写操作的时候,同一时刻的其他线程的读操作会被阻塞,当读操作的时候,同一时刻的写操作会被阻塞,读锁也被称共享锁,写锁被称为排它锁

在java中通过ReadWriteLock来实现读写锁,ReadWriteLock是接口,ReentrantReadWriteLock是它的具体实现方法,通过ReadLock和WriteLock两个内部类来实现读锁和写锁

package com.boom.example.demo.aa;

import java.lang.invoke.VarHandle;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCacheLock myCacheLock = new MyCacheLock();
        for(int i=1;i<=5;i++){
            final int temp = i;
            new Thread(()->{
                myCacheLock.put(String.valueOf(temp),temp);

            },String.valueOf(i)).start();
        }
        for(int i=1;i<=5;i++){
            final int temp = i;
            new Thread(()->{
                myCacheLock.get(String.valueOf(temp));

            },String.valueOf(i)).start();
        }
    }
}
class MyCacheLock{
    private volatile HashMap<String,Object> hashMap = new HashMap<>();
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    public void put(String s,Object obj){
        readWriteLock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "写入" + obj);
            hashMap.put(s,obj);
            System.out.println(Thread.currentThread().getName() + "写入完成");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.writeLock().unlock();
        }

    }
    public void get(String s){
        readWriteLock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "读取" + s);
            hashMap.get(s);
            System.out.println(Thread.currentThread().getName() + "读取完成");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.readLock().unlock();
        }
    }


}

BlockingQueue
 四组API
在这里插入图片描述
SynchronizedQueue
不存储元素

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值