尚硅谷JUC视频笔记整理

NotSafeDemo

list 不安全

List<String> list = new ArrayList<>();
//new Vector<>();
//Collections.synchronizedList(new ArrayList<>());
//new CopyOnWriteArrayList<>();
for (int i = 1; i <= 100; i++) {
    new Thread(() -> {
        list.add(UUID.randomUUID().toString().substring(0,8));
        System.out.println(list);
    }, String.valueOf(i)).start();
}
  • 当 i 即线程数过高时,ArrayList是非线程安全的容器,会出现 java.util.ConcurrentModificationException 故障问题,可以使用以上三种方法解决问题。
  • CopyOnWriteArrayList 容器即写时复制的容器。
    • 一个容器添加元系的时候,不直接往当前容器 Object[] 添加,而是先将当前容器Object[]进行 Copy ,复制出一个新的容器Object[] newELements ,然后新的容器 Object[] newELements里添加元素,添加完元素之后,再将原容器的引用指向新的容器 setArray( newELements);。这样做的好处是可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以 CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器

set 不安全

Set<String> set = new HashSet<>();
//Collections.synchronizedSet(new HashSet<>());
//new CopyOnWriteArraySet<>();
for (int i = 1; i <= 30; i++) {
    new Thread(() -> {
        set.add(UUID.randomUUID().toString().substring(0,8));
        System.out.println(set);
    }, String.valueOf(i)).start();
}
  • HashSet底层是HashMap,但HashSet只有一个值,HashMap有两个值,是因为HashMap传进 HashSet 的是 key 的值,而 value 是一个写死的常量。

map 不安全

Map<String, String> map = new HashMap<>();
//Collections.synchronizedMap()
//new ConcurrentHashMap();

for (int i = 1; i <= 30; i++) {
    new Thread(() -> {
        map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,8));
        System.out.println(map);
    }, String.valueOf(i)).start();
}


Callable 接口

class MyThread implements Runnable{
    @Override
    public void run() {

    }
}

class MyThread2 implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        return null;
    }
}

Callable接口:第3种获得多线程的方式

  • 异同:
    • 方法不同:一个是run,一个是call
    • 异常不同:Runnable没异常,Callable抛异常
    • 返回值不同:Runnable没返回值,Callable有返回值
/*MyThread myThread = new MyThread();// implements Callable<Integer>
  Thread t1 = new Thread(myThread);
  t1.start();*/

FutureTask futureTask = new FutureTask(new MyThread());
  • 调用Callable接口时不能使用new Thread(myThread),因为Thread中要传入Runnable参数,不能传Callable,所以要用FutureTask来实现Runnable和Callable接口,传入Callable参数12.21-1


JUC的辅助类

CountDownLatch(减少计数)

  • CountDownLatch主要有两个方法,
    • 当一个或多个线程调用 await方法时,这些线程会阻塞。
    • 其它线程调用 countDown方法会将计数器减1(调用 countDown方法的线程不会阻塞),当计数器的值变为8时,因 await方法阻塞的线程会被唤醒,继续执行。

12.21-2


CyclicBarrier(循环栅栏)

12.21-3


Semaphore(信号灯)

  • 在信号量上我们定义两种操作:
    • acquire(获取)当一个线程调用 acquire操作时,它要么通过成功获取信号量(信号量减1),
      要么一直等下去,直到有线程释放信号量,或超时
    • release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。
  • 信号量主要用于两个目的,一个是用于多个共享资源的互斥使用,另一个用于并发线程数的控制。

12.21-4



ReentrantReadWriteLock(读写锁)

12.21-5

/**
 * 多个线程同时读一个资源类没有任何问题,所以为了满足并发量,读取共享资源应该可以同时进行
 * 但是
 * 如果有一个线程想去写共享资源来,就不应该再有其它线程可以对该资源进行读或写
 * 小总结:
 *      读-读能共存
 *      读-写不能共存
 *      写-写不能共存
 */
public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCache myCache = new MyCache();

        for (int i = 1; i <= 5; i++) {
            final int tempInt = i;
            new Thread(() -> {
                myCache.put(tempInt+"",tempInt+"");
            },String.valueOf(i)).start();
        }

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

BlockingQueue(阻塞队列)

  • 在多线程领域:所谓阻塞,在某些情况下会挂起线程(即阻塞),一旦条件满足,被挂起的线程又会自动被唤起;
  • 好处:我们不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程。

12.22-1

12.22-2


ThreadPool线程池(ThreadPoolExecutor)

  • 线程池的优势:
    线程池做的工作只要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,超出数量的线程排队等候,等其他线程执行完毕,再从队列中取出任务来执行。
  • 主要特点:线程复用;控制最大并发数;管理线程。
    1. 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
    2. 提高响应速度。当任务到达时,任务可以不需要等待线程创建就能立即执行。
    3. 提髙线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会销耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

12.22-3

七大参数

  • 1、常驻线程;2、最大线程数;3、存活时间;4、时间单位;5阻塞队列;6、线程工厂;7、拒绝策略。
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    if (corePoolSize < 0 ||
        maximumPoolSize <= 0 ||
        maximumPoolSize < corePoolSize ||
        keepAliveTime < 0)
        throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;

12.22-4

12.22-5

设置合理参数-拒绝策略
ExecutorService threadPool = new ThreadPoolExecutor(
                2,
                5,
                2L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),
                Executors.defaultThreadFactory(),
                //new ThreadPoolExecutor.AbortPolicy());
                //new ThreadPoolExecutor.CallerRunsPolicy());
                //new ThreadPoolExecutor.DiscardPolicy());
                new ThreadPoolExecutor.DiscardOldestPolicy());

12.22-6


四大函数式接口

12.22-7

/*Function<String, Integer> function = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return 1024;
            }
        };
        System.out.println(function.apply("abc"));*/
        Function<String, Integer> function = s -> {return s.length();};
        System.out.println(function.apply("abc"));

        /*Predicate<String> predicate = new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return false;
            }
        };*/
        Predicate<String> predicate = s -> {return s.isEmpty();};
        System.out.println(predicate.test("abcde"));

        /*Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {

            }
        };*/
        Consumer<String> consumer = s -> { System.out.println(s); };
        consumer.accept("abcde");

        /*Supplier<String> supplier = new Supplier<String>() {
            @Override
            public String get() {
                return null;
            }
        };*/
        Supplier<String> supplier = () -> {return "java12.22";};
        System.out.println(supplier.get());

/*-------------------------------------------------------------------------------------------------*/
输出:
	3
	false
	abcde
	java12.22
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

庭户皓己盈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值