首页 > 其他分享 >JUC-2

JUC-2

时间:2023-09-26 16:36:02浏览次数:25  
标签:JUC System queue 线程 println new out

JUC-2

6、集合类不安全

list

package demo02;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

//.ConcurrentModificationException 并发修改异常
public class Day92300 {
    public static void main(String[] args) {
        /*
        并发下ArrayList不安全的吗,Synchronized ;
            解决方案;
            1、List<String>List = new Vector<> ();
            2、List<String>list = Collections.synchronizedList(new ArrayList<>());
            3、List<String> list = new CopyOnwriteArrayList<>();

            Copyonwrite 写入时复制Cow计算机程序设计领域的一种优化策略;
            多个线程调用的时候,List,读取的时候,固定的,写入(覆盖)
            在写入的时候避免覆盖,造成数据问题!

            读写分离Mycat

         */
        List<String> list = new CopyOnWriteArrayList<>();
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,5));
                //UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,
                // 主要是让让分布式系统中的所有元素,都能有唯一的辨识信息。随机生成UUID的标识符是UUID类中的方法
               // 而UUID.randomUUID().toString()是javaJDK提供的一个自动生成主键的方法
                System.out.println(list);
            },String.valueOf(i)).start();
        }

    }
}

set

package demo02;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
//ConcurrentModificationException,注:线程少可能不会出异常
public class Day92301 {
    public static void main(String[] args) {
        //2种方法
        // set<string> set = new Hashset<>();
        //set<string> set = collections.synchronizedset(new HashSet<>());

        Set<String> set = Collections.synchronizedSet(new HashSet<>());
        for (int i = 0; i < 30; i++) {
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0,5));
                //UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,
                // 主要是让让分布式系统中的所有元素,都能有唯一的辨识信息。随机生成UUID的标识符是UUID类中的方法
                // 而UUID.randomUUID().toString()是javaJDK提供的一个自动生成主键的方法
                System.out.println(set);
            },String.valueOf(i)).start();
        }
    }
}

hashSet 底层是什么?

public Hashset( {
map = new HashMap<>);
// add set本质就是map key是无法重复的!
    public boolean add(E e) {
return map. put(e,PRESENT)==nu1l;
private static final object PRESENT = new object(;// 不变的值!

Map不安全

package demo02;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

//ConcurrentModificationException
public class Day92302 {
    public static void main(String[] args) {
        /*
        map是这样用的吗?不是,工作中不用HashMap
        默认等价于什么?new HashMap<>(16,0.75);
        Map<String, String> map = new HashMap<>();
        唯一的一个家庭作业:研究concurrentHashMap的原理

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


7、Callable

1、可以有返回值

2、可以抛出异常

3、方法不同,run()/ call()

 new Thread( new FutureTask<V>( caLlable ) ).start();

package demo03;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Day92500 {
    public static void main(String[] args) {
        Mythread mythread = new Mythread();
        FutureTask futureTask = new FutureTask(mythread);
        Thread thread = new Thread(futureTask);//结果会被缓存,效率高

        thread.start();
        Object o = null;
        try {
            o = futureTask.get();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
        System.out.println(o);
    }
}
class Mythread implements Callable{

    @Override
    public Object call() throws Exception {
        System.out.println("999");
        return 555;
    }
}

Integer o = (Integer) futureTask.get();//这个get方法可能

会产生阻塞!把他放到最后

或者使用异步通信来处理!

细节:

1、有缓存
2、结果可能需要等待,会阻塞!

8、常用的辅助类

8.1、CountDownLatch

package demo03;

import java.util.concurrent.CountDownLatch;

//计数器
public class Day92501 {
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(6);//总数为6
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"  go out");
                countDownLatch.countDown();//数量减1
            },String.valueOf(i)).start();
        }
            try {
                countDownLatch.await();//等待计数器归零,然后再向下执行
                //必须要执行任务的时候,再使用!
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            System.out.println("close");

    }
}

原理:

  • countDownLatch. countDown;/数量-1
  • countDownLatch.awaitO;//等待计数器归零,然后再向下执行
  • 每次有线程调用countDown()数量-1,假设计数器变为0,countDownLatch.await()就会被唤醒,继续执行!

8.2、CyclicBarrier

加法计数器

package demo03;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Day92502 {
    public static void main(String[] args) {
        //集齐7颗龙珠召唤神龙
        //召唤龙珠的线程
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
            System.out.println("7777");
        });
        for (int i = 0; i < 7; i++) {
            final int temp=i;
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"收集第"+temp+"颗龙珠");
                try {
                    cyclicBarrier.await();//等待
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } catch (BrokenBarrierException e) {
                    throw new RuntimeException(e);
                }
            }).start();
        }


    }
}

8.3、Semaphore

信号量

package demo03;

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class Day92503 {
    public static void main(String[] args) {
        //线程数量:停车位,限流
        Semaphore semaphore = new Semaphore(3);
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                try {
                    semaphore.acquire();//得到
                    System.out.println(Thread.currentThread().getName()+"抢到车位");
                    TimeUnit.SECONDS.sleep(2);
                    System.out.println(Thread.currentThread().getName()+"离开车位");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } finally {
                    semaphore.release();//释放
                }
            }).start();
        }
    }
}

原理:

  • semaphore.acquire()
    获得,假设如果已经满了,等待,等待被释放为止!
  • semaphore.release();
    释放,会将当前的信号量释放+ 1,然后唤醒等待的线程!
  • 作用:多个共享资源互斥的使用!并发限流,控制最大的线程数!

9、读写锁

ReadWriteLock

package demo03;

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

public class Day92504 {
    public static void main(String[] args) {
        MyCacheLock myCache = new MyCacheLock();
        //写入
        for (int i = 0; i < 5; i++) {
            int temp=i;
            new Thread(()->{
                myCache.put(temp+"",temp+"");
            }).start();
        }
        //读取
        for (int i = 0; i < 5; i++) {
            int temp=i;
            new Thread(()->{
                myCache.get(temp+"");
            }).start();
        }
    }
}
//自定义缓存
class MyCache{
    private  volatile Map<String,Object> map=new HashMap<>();
    //存
    public void put(String key,Object value){
        System.out.println(Thread.currentThread().getName()+"写入"+key);
        map.put(key,value);
        System.out.println(Thread.currentThread().getName()+"写入完成");

    }
    //取
    public void get(String key){
        System.out.println(Thread.currentThread().getName()+"读取"+key);
        Object o = map.get(key);
        System.out.println(Thread.currentThread().getName()+"读取完成");

    }
}
//加锁的
class MyCacheLock{
    private  volatile Map<String,Object> map=new HashMap<>();
    //读写锁:更加细粒度的控制
    ReentrantReadWriteLock readWriteLock=new ReentrantReadWriteLock();

    //存,写入的时候,只希望同时只有一个线程写
    public void put(String key,Object value){
        readWriteLock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"写入"+key);
            map.put(key,value);
            System.out.println(Thread.currentThread().getName()+"写入完成");
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            readWriteLock.writeLock().unlock();
        }

    }
    //取,读,所有人都可以读!
    public void get(String key){
        readWriteLock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"读取"+key);
            Object o = map.get(key);
            System.out.println(Thread.currentThread().getName()+"读取完成");
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            readWriteLock.readLock().unlock();
        }

    }
}
独占锁(写锁)一次只能被一个线程占有
共享锁(读锁)多个线程可以同时占有
ReadwriteLock
读-读可以共存!
读-写不能共存!
写-写不能共存!



10、阻塞队列

  • 阻塞
  • 队列

写入:如果队列满了,就必须阻塞等待取:

如果是队列是空的,必须阻塞等待生产

BlockingQueue BlockingQueue不是新的东西

什么情况下我们会使用阻塞队列:多线程并发处理,线程池!

image-20230925180230796

什么情况下我们会使用阻塞队列:多线程并发处理,线程池!

学会使用队列

添加、移除

四组API

方式 抛出异常 有返回值 阻塞等待 超时等待
添加 add offer put offer
移除 remove poll take poll
检测队列首 element peek
//抛出异常
ArrayBlockingQueue<Object> queue = new ArrayBlockingQueue<>(3);
        System.out.println(queue.add("a"));//true
        System.out.println(queue.add("b"));
        System.out.println(queue.add("c"));
        //System.out.println(queue.add("d"));IllegalStateException
        System.out.println("======");
        System.out.println(queue.remove());//a
        System.out.println(queue.remove());
        System.out.println(queue.remove());
        //System.out.println(queue.remove());NoSuchElementException
    }
public void test(){
        //有返回值,没有异常
        ArrayBlockingQueue<Object> queue = new ArrayBlockingQueue<>(3);//队列大小
        System.out.println(queue.offer("a"));
        System.out.println(queue.offer("r"));
        System.out.println(queue.offer("e"));//true
        System.out.println(queue.offer("w"));//false
        System.out.println("-------");
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());//e
        System.out.println(queue.poll());//null
    }

等待,阻塞(一直阻塞)

public void test2() throws InterruptedException {
        ArrayBlockingQueue<Object> queue = new ArrayBlockingQueue<>(3);
        //一直阻塞
        queue.put("a");
        queue.put("c");
        queue.put("x");
      //  queue.put("x");  队列没有位置了,一直阻塞
        System.out.println(queue.take());
        System.out.println(queue.take());
        System.out.println(queue.take());
        //System.out.println(queue.take());没有这个元素,一直阻塞
    }

超时等待

public void test3() throws InterruptedException {
        ArrayBlockingQueue<Object> queue = new ArrayBlockingQueue<>(3);
        queue.offer("a");
        queue.offer("v");
        queue.offer("c");
        queue.offer("c",2, TimeUnit.SECONDS);//等待超过2秒就退出

        System.out.println("=========");
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll(2, TimeUnit.SECONDS));//等待超过2秒就退出. null

SynchronousQueue同步队列

没有容量
进去一个元素,必须等待取出来之后,才能再往里面放一个元素!

put、take

//同步队列
    //和其他的BLockingQueue不一样, SynchronousQueue不存储元素
    // put 了一个元素,必须从里面先take取出来,否则不能在put进去值!
    @Test
    public void test4(){
        SynchronousQueue<String> queue = new SynchronousQueue<String>();
        new Thread(()->{
            try {
                System.out.println(Thread.currentThread().getName()+"put1");
                queue.put("1");
                System.out.println(Thread.currentThread().getName()+"put2");
                queue.put("2");
                System.out.println(Thread.currentThread().getName()+"put3");
                queue.put("3");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();

        new Thread(()->{
            try {

                System.out.println(Thread.currentThread().getName()+"--"+queue.take());

                System.out.println(Thread.currentThread().getName()+"--"+queue.take());

                System.out.println(Thread.currentThread().getName()+"--"+queue.take());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();
    }

11、线程池(重点)

线程池:三大方法、7大参数、4种拒绝策略

池化技术

  • 程序的运行,本质︰占用系统的资源!优化资源的使用!=>池化技术
  • 线程池、连接池、内存池、对象池.....创建、销毁。十分浪费资源
  • 池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。

线程池的好处:

1、降低资源的消耗

2、提高响应的速度

3、方便管理。

线程复用、可以控制最大并发数、管理线程

package demo04;

import org.junit.Test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Day92600 {

    //Executors工具类、3大方法
    //使用了线程池之后,使用线程池来创建线程
    @Test
    public void test1(){
       // ExecutorService threadPool = Executors.newSingleThreadExecutor();///单个线程
        // ExecutorService threadPool = Executors.newFixedThreadPool(5);//创建一个固定的线程池的大小
        ExecutorService threadPool = Executors.newCachedThreadPool();//  可伸缩的,遇强则强,遇弱则弱

        try {
            for (int i = 0; i < 10; i++) {
                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"   ok");
                });
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            ///线程池用完,程序结束,关闭线程池
            threadPool.shutdown();
        }
    }

}

//本质ThreadPoo1Executor ()
public ThreadPoo1Executor(int corePoolsize,//核心线程池大小
int maximumPoo1size,//最大核心线程池大小
       long keepAliveTime,// 超时了没有人调用就会释放
 Timeunit unit,//超时单位
BlockingQueue<Runnable> workQueue,//阻塞队列
ThreadFactory threadFactory,//线程工厂:创建线程的,一般不用动
    RejectedExecutionHand1er handle//拒绝策略

image-20230926152258660

image-20230926152723836

四种拒绝策略

@Test
    public void test2() {
        ///自定义线程池!工作ThreadPooLExecutor
        ExecutorService threadPool = new ThreadPoolExecutor(
                2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                //new ThreadPoolExecutor.AbortPolicy()银行满了,还有人进来,不处理这个人的,抛出异常
                //new ThreadPoolExecutor.CallerRunsPolicy()///哪来的去哪里! main   ok
                //new ThreadPoolExecutor.DiscardPolicy() //队列满了,丢掉任务,不会抛出异常!
                new ThreadPoolExecutor.DiscardOldestPolicy() //队列满了,尝试去和最早的竞争,也不会抛出异常!|

        );

        try {
            //最大承载: Deque +max
            for (int i = 0; i < 19; i++) {
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "   ok");
                });
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            ///线程池用完,程序结束,关闭线程池
            threadPool.shutdown();
        }
    }

最大线程到底该如何定义

1、CPU密集型,几核,就是几,可以保持cPu的效率最高!

2、Io密集型 >判断你程序中十分耗工o的线程,

程序15个大型任务 io十分占用资源!

获取CPU的核数

system.out.println(Runtime.getRuntime( ).availableProcessors( ));


12、四大函数式接口(必需掌握)

新时代的程序员:lambda表达式、链式编程、函数式接口、Stream流式计算

函数式接口:只有一个方法的接口

  • 超级多FunctionalInterface

  • 简化编程模型,在新版本的框架底层大量应用!

  • foreach(消费者类的函数式接口)

  • Function函数式接口

Function函数型接口,有一个输入参数,有一个输出只要是函数型接口可以用lambda表达式简化

  • 断定型接口

有一个输入参数,返回值只能是布尔值!

  • Consumer消费型接口

    消费型接口:只有输入,没有返回值

  • Supplier供给型接口

​ 供给型接口没有参数,只有返回值

标签:JUC,System,queue,线程,println,new,out
From: https://www.cnblogs.com/xin-zhi-suo-xiang/p/17730382.html

相关文章

  • JUC-1
    JUC-11、什么是JUC源码+官方文档面试高频问!java.util工具包、包、分类业务∶普通的线程代码ThreadRunnable没有返回值、效率相比入Callable相对较低!2、线程和进程线程、进程,如果不能使用一句话说出来的技术,不扎实!进程:—个程序,QQ.exeMusic.exe程序的集合;一个进程往......
  • 全网最详细Java-JUC
    Java-JUC⓪基础❶进程&线程进程:指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间。线程:比进程更小的执行单位,一个进程可以启动多个线程,每条线程并行执行不同的任务。❷并行&并发并行(Parallel):在同一时刻,有多个指令在多个CPU上同时执行。并发(Concurrent):在......
  • 25届实习秋招-Java面试-JUC多线程面试题整理-牛客网
    JUC介绍一下JUC下的锁(如何使用及应用场景)线程什么是进程:特征什么是线程:资源为什么多线程,什么使用用单线程,什么时候多线程,什么条件下多线程快。进程和线程的对比:进程如何通信,每种通信存放的介质。||线程的通信,几种方式。join进程和线程的区别,在JVM层面的体现一......
  • Java多线程____JUC并发锁机制
    1.同步锁即通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁。同步锁的原理是,对于每一个对象,有且仅有一个同步锁;不同的线程能共同访问该同步锁但是,在同一个时间点,该同步锁能且只能被一个线程获取到。这样,获取到同步锁的线程就能进行CPU调度,从而在CPU上执行;而没有获......
  • JUC并发编程
    JUC并发编程1.什么是JUCjava.util工具包,包,分类业务:普通的线程代码ThreadRunable没有返回值,效率相比Callable相对较低!2.线程和进程线程、进程、如果不能使用一句话说出来的技术,不扎实!进程:一个程序,例如qq.exe,代表一个程序的集合一个进程往往包含多个线程,而一个进......
  • JUC
    一、JUC1.概念从Java5开始,在JDK中多出了java.util.concurrent包(简称:JUC)。JUC主要是让开发者在多线程编程中更加简单、方便一些。通过JDK内置了一些类、接口、关键字,补充完善了JDK对于并发编程支持的“短板”。2.主要包含功能Executor:线程池Atomic:原子操......
  • AQS和JUC面试题
    【讲义】第2讲:AQS和JUC⼀、ReentrantLock重⼊锁1.1>概述1.2>中断响应lockInterruptibly()1.3>锁申请等待限时tryLock(longtime,TimeUnitunit)1.4>公平锁和⾮公平锁1.5>AQS源码解析⼆、Condition重⼊锁的搭配类三、Semaphore信号量四、ReadWriteLock读写锁五、C......
  • 【转载】JUC常见面试题:Java线程和操作系统线程有什么区别
    【转载】JUC常见面试题:Java线程和操作系统线程有什么区别整理来自于:https://cloud.tencent.com/developer/article/18181511操作系统的用户态和核心态在操作系统中,内存通常会被分成用户空间(Userspace)与内核空间(Kernelspace)这两个部分。当进程/线程运行在用户空间时就处于用......
  • java juc相关
    JUC全称JavaUtilConcurrency,是java中用于并发编程的工具类库,提供了丰富的类和接口,用于管理多线程,支持同步互斥操作。JUC特点:高效性:JUC提供了高度优化的并发控制机制,可以提高多线程应用程序的执行效率和吞吐量。可扩展性:JUC支持灵活的扩展和定制,提供了各种类和接口,可以根据需......
  • JUC
    1、什么是JUCjava.util工具包、包、分类业务:普通的线程代码ThreadRunnable没有返回值、效率相比入Callable相对较低!2、进程和线程回顾进程:一个程序,QQ.exeMusic.exe程序的集合;一个进程往往可以包含多个线程,至少包含一个!Java默认有几个线程?2个mian、GC......