#java常用代码片段(代码片段)

爱码代码的喵 爱码代码的喵     2022-10-22     570

关键词:

Java 常用代码片段

延迟队列

  • JDK 中提供了一组实现延迟队列的API,位于Java.util.concurrent包下DelayQueue
    DelayQueue是一个BlockingQueue(无界阻塞)队列,它本质就是封装了一个PriorityQueue(优先队列),PriorityQueue内部使用完全二叉堆(来实现队列元素排序,我们在向DelayQueue队列中添加元素时,会给元素一个Delay(延迟时间)作为排序条件,队列中最小的元素会优先放在队首。队列中的元素只有到了Delay时间才允许从队列中取出。

  • DelayDemo.java

public class DelayDemo implements Delayed 

    /**
     * 延迟时间
     */
    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Long time;

    /**
     * 任务名称
     */
    private String name;


    public DelayDemo(Long time, String name, TimeUnit unit) 
        this.time = System.currentTimeMillis() + (time > 0 ? unit.toMillis(time) : 0);
        this.name = name;
    

    /**
     * 获取延迟时间
     *
     * @param unit unit
     * @return long
     */
    @Override
    public long getDelay(TimeUnit unit) 
        return time - System.currentTimeMillis();
    

    /**
     * 对延迟队列中的元素进行排序
     *
     * @param o
     * @return int
     */
    @Override
    public int compareTo(Delayed o) 
        DelayDemo delayDemo = (DelayDemo) o;
        return time.compareTo(delayDemo.getTime());
    

    public Long getTime() 
        return time;
    

    public void setTime(Long time) 
        this.time = time;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

  • DelayQueueTest.java
public class DelayQueueTest 

    private static final Logger logger = LoggerFactory.getLogger(DelayQueueTest.class);

    @Test
    public void test() throws InterruptedException 
        DelayDemo delayDemo1 = new DelayDemo(5l, "订单1", TimeUnit.SECONDS);
        DelayDemo delayDemo2 = new DelayDemo(10l, "订单2", TimeUnit.SECONDS);
        DelayDemo delayDemo3 = new DelayDemo(15l, "订单3", TimeUnit.SECONDS);

        DelayQueue<DelayDemo> delayQueue = new DelayQueue<>();
        delayQueue.add(delayDemo1);
        delayQueue.add(delayDemo2);
        delayQueue.add(delayDemo3);

        logger.info("延迟队列开始时间:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        while (delayQueue.size() != 0) 
            DelayDemo delayDemo = delayQueue.poll();
            if (Objects.nonNull(delayDemo)) 
                logger.info("任务:" + delayDemo.getName() + "被取消, 取消时间: " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            
            Thread.sleep(1000);
        
    

线程池 ThreadPoolExecutor

参数说明

  • corePoolSize:核心线程数
  • maxPoolSize:最大线程数,当阻塞队列满了的时候会使用最大线程数的线程提交任务
  • keepAliveTime:线程空闲的时候保持活跃的时间

队列

  • ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序
  • LinkedBlockingQueue一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列
  • SynchronousQueue:不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。
  • PriorityBlockingQueue:具有优先级的无限阻塞队列。

拒绝策略

  • 当提交的任务数大于队列和最大线程数的时候就会触发线程池的拒绝策略。

  • AbortPolicyThreadPoolExecutor中默认的拒绝策略就是AbortPolicy,直接抛出异常。

  • CallerRunsPolicy :使用该策略时线程池饱和后将由调用线程池的主线程自己来执行任务,因此在执行任务的这段时间里主线程无法再提交新任务,从而使线程池中工作线程有时间将正在处理的任务处理完成。

  • DiscardPolicy :不做任何处理直接抛弃任务。

  • DiscardOldestPolicy :先将阻塞队列中进入最早的任务丢弃,再尝试提交任务。

示例代码

@Test
public void test2() 
    // 核心线程数
    int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;
    // 最大线程数
    int maxPoolSize = Runtime.getRuntime().availableProcessors() << 1;
    // 当线程空闲时,保持活跃的时间 1000 毫秒 1s
    int keepAliveTime = 1000;
    // 阻塞队列大小
    int blockQueueSize = 1000;

    ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize,
                                                           maxPoolSize,
                                                           keepAliveTime,
                                                           TimeUnit.MILLISECONDS,
                                                           new LinkedBlockingQueue<>(blockQueueSize),
                                                           new ThreadPoolExecutor.AbortPolicy());

    threadPool.execute(() -> 
        logger.info("自定义线程池的使用...");
    );
    try 
        Thread.sleep(3000);
     catch (InterruptedException e) 
        logger.error("Error occur:", e);
    

创建线程

获取线程执行结果(Callable)

  • 可以拿到线程中抛出的异常。
  • 线程执行完成后可以返回结果。

示例

  • DoOneCallable.java
public class DoOneCallable implements Callable<Object> 

    private static final Logger logger = LoggerFactory.getLogger(DoOneCallable.class);

    @Override
    public Object call() 
        try 
            logger.info("test Thread!");
            return 4 / 0;
         catch (Exception e) 
            throw e;
        
    

  • CallableTest.java
public class CallableTest 

    private static final Logger logger = LoggerFactory.getLogger(CallableTest.class);

    /**
     * Callable 的使用场景:加入子线程中有错误抛出、或者拿到线程执行的结果
     *
     * @param args args
     */
    public static void main(String[] args) 
        Callable<Object> callable = new DoOneCallable();
        FutureTask<Object> futureTask = new FutureTask<>(callable);
        try 
            // run 方法启动线程
            futureTask.run();
            // get() 获得当前线程的执行结果
            futureTask.get();
         catch (Exception e) 
            logger.error("Error occur:", e.getMessage());
        
        logger.info("hello!");
    

    /**
     * callable 可以拿到线程中的异常
     */
    @Test
    public void test() 
        Callable<Object> callable = new DoOneCallable();
        try 
            callable.call();
         catch (Exception e) 
            logger.error("Error occur:", e.getMessage());
        
    

实现Runnable

  • 使用Runnable创建线程可以达到共享资源的目的
  • 外部无法捕获线程中的异常和结果

示例

public class CreateThreadByRunnableTest 

    private static final Logger logger = LoggerFactory.getLogger(CreateThreadByRunnableTest.class);
    private static final int TICKET_NUM = 11;

    /**
     * 使用 Runnable 的方式创建代码可以达到相同代码公用共同的资源
     */
    @Test
    public void test() 
        int num = 10;
        BuyTicketsRunnable buyTicketsRunnable = new BuyTicketsRunnable(num);
        for (int i = 0; i < TICKET_NUM; i++) 
            Thread thread = new Thread(buyTicketsRunnable);
            thread.start();
            if (Thread.holdsLock(Thread.currentThread())) 
                logger.info("当前线程持有对象监视器!");
            
        
    

    class BuyTicketsRunnable implements Runnable 

        private final Logger logger = LoggerFactory.getLogger(BuyTicketsRunnable.class);

        private int num;

        BuyTicketsRunnable(int ticketNum) 
            this.num = ticketNum;
        

        @Override
        public void run() 
            synchronized (this) 
                if (num > 0) 
                    num--;
                    logger.info("Thread  买到一张票 还剩: 张票", Thread.currentThread().getId(), num);
                 else 
                    logger.info("Thread  没有抢到票 还剩: 张票", Thread.currentThread().getId(), num);
                
            
        
    

继承Thread重写run()

  • 继承Thread,重写run方法,Thread类实现Runnable接口
  • class Thread implements Runnable

示例代码

public class CreateThreadByThreadTest 

    private static final Logger logger = LoggerFactory.getLogger(CreateThreadByThreadTest.class);

    @Test
    public void test() 
        new TestExtendsThread().start();
    

    class TestExtendsThread extends Thread 
        @Override
        public void run() 
            logger.info("我是Test1ExtendsThread的线程!");
        
    

Executors四种类型的线程池

  • 通过源码分析得出还是对ThreadPoolExecutor的使用,指定对应参数达到一定的效果

newFixedThreadPool

  • newFixedThreadPool(n):创建一个指定工作线程数量的线程池,如果线程数量达到初始化大小,则将提交的任务保存到池队列中。提高效率节省开销,不会释放空闲资源。
public static void userFixThreadPool() throws InterruptedException 
    ExecutorService executor = Executors.newFixedThreadPool(3);
    for (int i = 0; i < 10; i++) 
        Thread.sleep(1000);
        int index = i;
        executor.execute(() -> 
            try 
                Thread.sleep(2 * 1000);
             catch (InterruptedException e) 
                logger.error(e.getMessage(), e);
            
            logger.info("  ", Thread.currentThread().getName(), index);
        );
    
    executor.shutdown();

newCachedThreadPool

  • newCachedThreadPool():缓存线程池,可以灵活收回空闲线程,若无可回收则创建新的。默认为1分钟。
private void useCachedThreadPool(int y) throws Exception 
    ExecutorService executor = Executors.newCachedThreadPool();
    for (int i = 0; i < y; i++) 
        int index = i;
        Thread.sleep(4000);
        executor.execute(() -> logger.info("  ", Thread.currentThread().getName(), index));
    

newSingThreadExcutor

  • newSingThreadExcutor():只创建唯一的工作线程来执行任务,保证线程按照指定的书序执行,保证顺序的执行任务。
private void useSingleThreadExecutor() 
    // 单线程的线程池底层是创建一个核心线程为1最大线程为1的 threadPool
    ExecutorService executor = Executors.newSingleThreadExecutor();
    for (int i = 0; i < 5; i++) 
        int index = i;
        executor.execute(() -> 
            try 
                Thread.sleep(TWO_THOUSAND);
             catch (InterruptedException e) 
                logger.error(e.getMessage(), e);
                Thread.currentThread().interrupt();
            
            logger.info("   ", Thread.currentThread().getName(), index);
        );
    
    executor.shutdown();

newScheduledThreadPool

  • newScheduledThreadPool(n):支持定时及周期性任务执行。
public static void useScheduledThreadPool() 
    ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
    executor.scheduleAtFixedRate(() -> 
        long start = System.currentTimeMillis();
        logger.info("scheduleAtFixedRate 开始执行时间:", DateFormat.getTimeInstance().format(new Date()));
        try 
            Thread.sleep(5000);
         catch (InterruptedException e) 
            logger.error(e.getMessage(), e);
        
        long end = System.currentTimeMillis();
        logger.info("scheduleAtFixedRate 执行花费时间=m", (end - start) / 1000);
        logger.info("scheduleAtFixedRate 执行完成时间:", DateFormat.getTimeInstance().format(new Date()));
        logger.info("======================================");
    , 1, 5, TimeUnit.SECONDS);

线程计数器CountDownLatch

  • CountDownLatch可以使一个获多个线程等待其他线程各自执行完毕后再执行。
  • CountDownLatch 定义了一个计数器,和一个阻塞队列, 当计数器的值递减为0之前,阻塞队列里面的线程处于挂起状态,当计数器递减到0时会唤醒阻塞队列所有线程,这里的计数器是一个标志,可以表示一个任务一个线程,也可以表示一个倒计时器,CountDownLatch可以解决那些一个或者多个线程在执行之前必须依赖于某些必要的前提业务先执行的场景。
public class CountDownLatchTest 

    private static final Logger logger = LoggerFactoryjava[java]java常用代码#java(代码片段)

查看详情

java常用加密方式-java实现(代码片段)

查看详情

java347.topk常用元素(代码片段)

查看详情

java此类中添加了常用功能(代码片段)

查看详情

java常用单位转换的辅助类(代码片段)

查看详情

java常用(代码片段)

  排序//**冒泡importjava.util.Arrays;classtest publicstaticvoidmain(String[]args)int[]arr=3,44,38,5,47,15,36,26,27,2,46,4,19,50,48; bubbleSort(arr); publicstaticvoidbubbleSort(int[]a) inttemp; //因为是 查看详情

java番石榴常用操作学习(代码片段)

查看详情

java常用单位转换的辅助类(代码片段)

查看详情

java常用的正则表达式(代码片段)

查看详情

java常用单位转换的辅助类(代码片段)

查看详情

java常用类(代码片段)

常用类包装类Wrapper的分类包装类和基本数据的转换01:packageTryCatchExercise;publicclassWrapperDemopublicstaticvoidmain(String[]args)//手动装箱intn1=100;Integerinteger=newInteger(n1);Integerinteger1=Integer.valueO 查看详情

java常用常量类(代码片段)

publicclassStringConstantprivatefinalstaticStringISO_8859_1="ISO-8859-1";privatefinalstaticStringGB2312="GB2312";privatefinalstaticStringUTF_8="UTF-8";publicstaticf 查看详情

java常用常量类(代码片段)

publicclassStringConstantprivatefinalstaticStringISO_8859_1="ISO-8859-1";privatefinalstaticStringGB2312="GB2312";privatefinalstaticStringUTF_8="UTF-8";publicstaticf 查看详情

java自定义视图常用的方法工具(代码片段)

查看详情

java常用工具类封装(代码片段)

java常用工具类封装importorg.apache.commons.lang.StringUtils;importjava.math.BigDecimal;publicclassCommonUtilpublicstaticStringsafeToString(Objectvalue,StringdefaultValue)if(value!=null)returnStringUti 查看详情

程序员常用指令(代码片段)

程序员常用指令文章目录程序员常用指令环境变量windows下环境变量配置Java环境变量anaconda环境变量maven环境变量mysql环境变量Linux下环境变量配置java环境变量anaconda环境变量mysql环境变量Java常用指令Maven常用指令Python常用指令Anacon... 查看详情

java常用类--string类常用方法(代码片段)

1.String类常用方法1.1String的判断常用方法演示:publicstaticvoidmain(String[]args)//创建字符串对象Strings1="hello";Strings2=newString("hello");Strings3=newString("HELLO");//booleanequals 查看详情

java_常用类(代码片段)

...va_字符串相关类Java_String类Java_字符串使用陷阱Java_string类常用方法Java_StringBuffer类Java_StrigBuffer类常用方法Java_StringBuilder类Java_日期时间APIJava_JDK8之前的日期时间APIJava_JDK8中新日期时间APIJava_字符串相关类Java_String类String的特性:1.Str 查看详情