首页 > 其他分享 >线程池的七种创建方式,线程池的拒绝策略,线程池看这篇就够了

线程池的七种创建方式,线程池的拒绝策略,线程池看这篇就够了

时间:2023-06-22 22:13:28浏览次数:58  
标签:Thread 七种 池看 任务 线程 new 执行 public

转载自:https://blog.csdn.net/weixin_48271092/article/details/124419062

线程池

一、线程存在的问题

之前我们已经学习过了线程,线程的创建方式我们讲了7种,感兴趣的小伙伴可以去看看前面的讲解。线程的创建

那么我们学习了那么多关于线程的知识,为什么还要再用到线程池呢?那么我们就要来思考一下,线程有什么问题吗?

  • 首先,每次有任务来时就要创建线程,任务结束就要将这个线程销毁,频繁的创建和销毁需要一定的开销。
  • 当任务数远远大于线程可以承载的数量之后,不能友好的进行任务拒绝。

因此引出了线程池~~

二、什么是线程池?

线程池是使用池化技术管理和使用线程的一种机制。

池化技术:提前准备一些资源,在需要时可以重复使用使用提前准备的资源。
池化技术的应用也比较多:

  • 内存池:预先申请内存,在 使用时提升申请内存的速度,减少内存碎片。
  • 数据库连接池:预先申请数据库连接,提升申请连接的速度,降低系统开销。

三、线程池的优点

线程池相比线程来说,它不需要频繁的创建和销毁线程,而是提前将线程创建好休眠在线程池中,有任务需要它时再唤醒它,线程一旦创建就不会销毁,会放入线程池中,如下图:
在这里插入图片描述
因此,他有以下几个优点:

  1. 复用线程,避免线程重复创建和销毁线程的性能开销。
  2. 控制线程的数量 ,从而避免了因创建线程过多而导致的内存溢出(OOM).
  3. 提供了任务管理的功能。从而可以实现任务缓存和任务拒绝的情况。
  4. 线程池提供了更多功能,比如延时任务。

四、线程池的使用

线程池的实现总的来说有两类:

  • 通过ThreadPoolExecutor创建的线程池;
  • 通过Executors创建的线程池。

线程池的创建方式总共包含以下7种(其中6种是通过Executors 创建的,1种是通过ThreadPoolExecutor创建的):

  • Executors.newFixedThreadPool:创建一个固定大小的线程池,可以控制并发的线程数,超出的线程会在队列中等待;
  • Executors.newCachedThreadPool:创建一个可缓存的线程池,若线程超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程;
  • Executors.newScheduledThreadPool:创建一个可以执行延迟任务的线程池;
  • Executors.newSingleThreadExecutor:创建单个线程的线程池,它可以保证先进先出的执行顺序
  • Executors.newSingleThreadScheduledExecutor:创建一个可以执行延迟任务的单个线程的线程池;
  • Executors.newWorkStealingPool:创建一个抢占式执行的线程池;
  • ThreadPoolExecutor:手动创建线程池 的方式,它最多包含了7个参数可供设置,最少可设置5个参数。

4.1 固定数量的线程池

4.1.1 具体实现

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

/**
 * 创建一个固定大小的线程池
 */
public class ThreadPoolDemo1 {
    public static void main(String[] args) {
        //1.创建了一个包含了5个线程的线程池
        ExecutorService threadPool= Executors.newFixedThreadPool(5);

        //2,使用线程池执行任务二(给线程池添加任务)
        for (int i = 0; i < 10; i++) {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("线程名称:"+Thread.currentThread().getName());
                }
            });
        }
    }
}

1234567891011121314151617181920212223

在这里插入图片描述

public class ThreadPoolDemo1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //1.创建了一个包含了5个线程的线程池
        ExecutorService threadPool= Executors.newFixedThreadPool(5);
        //2,使用线程池执行任务(给线程池添加任务)
        for (int i = 0; i < 5; i++) {
            Future<Integer> result = threadPool.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    int num=new Random().nextInt(9);
                    System.out.println("随机数:"+num);
                    return num;
                }
            });
            System.out.println("线程池的返回结果:"+result.get());
        }
    }
}

12345678910111213141516171819

在这里插入图片描述

观察上面这两段代码,我们可以发现,向线程池中添加任务的方式有两种:

  • execute:只能执行不带返回值的任务;
  • submit:它可以执行有返回值的任务或者是没有返回值的任务 。
    在这里插入图片描述
    在这里插入图片描述

4.1.2 线程工厂

在上面的执行中,可以看到没有设置线程的名称时,它就会是一个默认名 ,线程工厂可以让我们自定义线程名称或优先级
下面来看一下线程工厂的实现吧~

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

/**
 * 线程工厂的演示
 */
public class ThreadPoolDemo3 {
    public static void main(String[] args) {
       //1.创建线程工厂
        ThreadFactory threadFactory=new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread=new Thread(r);
                //设置线程命名规则
                thread.setName("我的线程-"+r.hashCode());
                //设置线程优先级
                thread.setPriority(Thread.MAX_PRIORITY);
                return thread;
            }
        };
        ExecutorService threadPool = Executors.newFixedThreadPool(5, threadFactory);
        for(int i=0;i<5;i++){
            threadPool.submit(()->{
                //任务
                Thread thread = Thread.currentThread();
                System.out.println("线程池开始执行了:"+thread.getName()+" "+thread.getPriority());
            });
        }
    }
}

1234567891011121314151617181920212223242526272829303132

在上面的代码中我们设置了线程的名称和优先级,看看他会生效吗?
在这里插入图片描述
答案是肯定的,但是要注意的是我们一定要将任务传入这个线程工厂,否则就会出错。在这里插入图片描述
如果我们什么都不传入,就会是什么都不打印。
在这里插入图片描述

4.3 带缓存的线程池

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

/**
 * 带缓存的线程池
 */
public class ThreadPoolDemo4 {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newCachedThreadPool();
        for(int i=0; i<1000; i++){
            int finalI=i;
            threadPool.submit(()->{
                System.out.println("i:"+finalI+"|线程名称:"+Thread.currentThread().getName());
            });
        }
    }
}

123456789101112131415161718

在这里插入图片描述
有1000个任务并不会创建1000个线程,通过执行可以发现最多会创建100多个线程,然后进行复用。

4.4 执行定时任务的线程池

4.4.1 延迟执行(一次)

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 创建执行定时任务的线程池
 */
public class ThreadPoolDemo5 {
    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
        System.out.println("添加任务的时间:"+ LocalDateTime.now());
        scheduleTest(service);//只执行一次的定时任务

    /**
     * 只执行一次的定时任务
     * @param service
     */
    private static void scheduleTest(ScheduledExecutorService service) {
        //执行定时任务(延迟3秒执行)
        service.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行了任务:"+LocalDateTime.now());
            }
        },3, TimeUnit.SECONDS);
    }
}

1234567891011121314151617181920212223242526272829

在这里插入图片描述
这是延迟执行任务,他只能执行一次。
创建这个线程池时有3个参数:

  1. 执行任务
  2. 延迟 n秒执行
  3. 配合2执行的时间单位

4.4.2 固定频率执行

我们可以让线程以以固定频率间隔n秒执行,创建这个线程池有四个参数:

  1. 执行任务
  2. 延迟n秒执行
  3. 执行定时任务的频率
  4. 配合3执行的时间单位
4.4.2.1 scheduleAtFixedRate
import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 创建执行定时任务的线程池
 */
public class ThreadPoolDemo5 {
    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
        System.out.println("添加任务的时间:"+ LocalDateTime.now());

        //2S之后开始执行定时任务,定时任务每4s执行一次
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务:"+LocalDateTime.now());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },2,4,TimeUnit.SECONDS);
    }
}

12345678910111213141516171819202122232425262728

在这里插入图片描述

4.4.2.2 scheduleWithFixedDelay
import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 创建执行定时任务的线程池
 */
public class ThreadPoolDemo5 {
    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
        System.out.println("添加任务的时间:"+ LocalDateTime.now());


//        //2S之后开始执行定时任务,定时任务每4s执行一次
//        service.scheduleAtFixedRate(new Runnable() {
//            @Override
//            public void run() {
//                System.out.println("执行任务:"+LocalDateTime.now());
//                try {
//                    Thread.sleep(1000);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//            }
//        },2,4,TimeUnit.SECONDS);

        //2s之后开始执行,每次执行间隔4s
        service.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务:"+LocalDateTime.now());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },2,4,TimeUnit.SECONDS);
    }
}

123456789101112131415161718192021222324252627282930313233343536373839404142

在这里插入图片描述

4.4.2.3 scheduleAtFixedRate VS scheduleWithFixedDelay

看出这两个方法的区别了吗?

scheduleAtFixedRate是以上一次任务开始的时间,加上任务的执行周期,作为下一次定时任务的开始时间。
在这里插入图片描述
scheduleWithFixedDelay是以上一次任务的结束时间,加上任务的执行周期,作为下次定时任务的开始时间。

在这里插入图片描述

注意:
在scheduleAtFixedRate中,有时任务的执行时间大于延迟任务设定的时间间隔,那么当任务执行完之后才会开始执行下次任务,此时并不是以设定执行周期来执行任务。

ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
        System.out.println("添加任务的时间:"+ LocalDateTime.now());
//        scheduleTest(service);//只执行一次的定时任务

        //2S之后开始执行定时任务,定时任务每4s执行一次
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务:"+LocalDateTime.now());
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },2,2,TimeUnit.SECONDS);
12345678910111213141516

在这里插入图片描述

4.5 单线程的线程池

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

/**
 * 单个线程的线程池
 */
public class ThreadPoolDemo7 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            int finalI=i;
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("任务名:"+finalI+"线程名:"+Thread.currentThread().getName());
                }
            });
        }
    }
}

123456789101112131415161718192021

在这里插入图片描述
那么肯定有同学有疑问了,单线程的线程池与单线程有什么区别呢?他有什么作用呢?

  1. 首先因为他是线程池,所有它能够提供任务队列和任务管理的功能,防止内存溢出。
  2. 其次它可以自定义拒绝策略(本文最后会讲到拒绝策略)

4.6 定时任务的单线程线程池

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 创建单线程的执行定时任务的线程池
 */
public class ThreadPoolDemo6 {
    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        System.out.println("执行任务的时间:"+LocalDateTime.now());
        service.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行任务:"+ LocalDateTime.now());
            }
        },2, TimeUnit.SECONDS);
    }
}

123456789101112131415161718192021

在这里插入图片描述

4.7 根据当前CPU生成线程池

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

/**
 * 根据当前设备的配置自动生成线程池
 */
public class ThreadPoolDemo8 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newWorkStealingPool();
        for (int i = 0; i < 100; i++) {
            int finalI=i;
            executorService.submit(()->{
                System.out.println("任务:"+finalI+"线程名:"+Thread.currentThread().getName());
            });
        }
        while (!executorService.isTerminated()){};
    }
}

12345678910111213141516171819

在这里插入图片描述

4.8 ThreadPoolExecutor的使用

4.8.1 Executors自动创建线程池可能存在的问题

根据阿里巴巴Java开发手册规定:
在这里插入图片描述

4.8.2 ThreadPoolExecutor使用

在这里插入图片描述
参数说明:

  • corePoolSize:核心线程数
  • maximumPoolSize:最大线程数(包含核心线程数)
  • keepAliveTime:空闲线程的存活时间
  • TimeUnit:时间单位
  • BlockingQueue:任务队列,用于存储线程池的待执行任务的
  • ThreadFactory:线程工厂,用于生成线程
  • handler:拒绝策略

具体实现:

import java.util.concurrent.*;

/**
 * 手动方式创建线程池
 */
public class ThreadPoolDemo10 {
    public static void main(String[] args) {
        ThreadFactory factory=new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread=new Thread(r);
                return thread;
            }
        };
        ThreadPoolExecutor executor=new ThreadPoolExecutor(2,5,10,
                TimeUnit.SECONDS,new LinkedBlockingDeque<>(2),factory,new ThreadPoolExecutor.DiscardPolicy());
        for (int i = 1; i < 6; i++) {
            int finalI=i;
            executor.submit(()->{
                try {
                    Thread.sleep(10*finalI);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("任务:"+finalI);
            });
        }
    }
}

123456789101112131415161718192021222324252627282930

4.8.3 线程池的执行流程

在这里插入图片描述
关键执行步骤:

  1. 当线程池中有任务时,先判断线程池是否在运行状态;
  2. 判断线程池中的线程数是否小于核心线程数,如果小于则添加工作线程并执行;
  3. 若线程池中的线程数不小于核心线程数,则判断阻塞队列是否已满,如果未满,则添加到阻塞队列,等待工作线程获取执行;
  4. 若阻塞队列已满,则判断线程数是否小于最大线程数,若小于,则添加工作线程并执行;
  5. 否则执行拒绝策略。

4.8.4 拒绝策略

线程池的拒绝策略共有5种(4种JDK提供的+1种自定义拒绝策略):

1.AbortPolicy()

提示异常拒绝执行,是默认的拒绝策略:

import java.util.concurrent.*;

/**
 * 手动方式创建线程池
 */
public class ThreadPoolDemo10 {
    public static void main(String[] args) {
        ThreadFactory factory=new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread=new Thread(r);
                return thread;
            }
        };
        ThreadPoolExecutor executor=new ThreadPoolExecutor(2,2,10,
                TimeUnit.SECONDS,new LinkedBlockingDeque<>(2),factory,new ThreadPoolExecutor.AbortPolicy());
        for (int i = 0; i < 5; i++) {
            int finalI=i;
            executor.submit(()->{
                try {
                    Thread.sleep(10*finalI);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("任务:"+finalI);
            });
        }
    }
}

123456789101112131415161718192021222324252627282930

在这里插入图片描述
2.DiscardPolicy()

丢弃任务但不抛出异常。如果线程数大于最大核心线程数,则后续提及的任务都会被丢弃,且是静默丢弃。

import java.util.concurrent.*;

/**
 * 手动方式创建线程池
 */
public class ThreadPoolDemo10 {
    public static void main(String[] args) {
        ThreadFactory factory=new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread=new Thread(r);
                return thread;
            }
        };
        ThreadPoolExecutor executor=new ThreadPoolExecutor(2,2,10,
                TimeUnit.SECONDS,new LinkedBlockingDeque<>(2),factory,new ThreadPoolExecutor.DiscardPolicy());
        for (int i = 0; i < 5; i++) {
            int finalI=i;
            executor.submit(()->{
                try {
                    Thread.sleep(10*finalI);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("任务:"+finalI);
            });
        }
    }
}

123456789101112131415161718192021222324252627282930

在这里插入图片描述

3.DiscardOldestPolicy()

丢弃阻塞队列最前面的任务,然后重新提交被拒绝的任务。

import java.util.concurrent.*;

/**
 * 手动方式创建线程池
 */
public class ThreadPoolDemo10 {
    public static void main(String[] args) {
        ThreadFactory factory=new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread=new Thread(r);
                return thread;
            }
        };
        ThreadPoolExecutor executor=new ThreadPoolExecutor(2,2,10,
                TimeUnit.SECONDS,new LinkedBlockingDeque<>(2),factory,new ThreadPoolExecutor.DiscardOldestPolicy());
        for (int i = 0; i < 5; i++) {
            int finalI=i;
            executor.submit(()->{
                try {
                    Thread.sleep(10*finalI);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("任务:"+finalI);
            });
        }
    }
}

123456789101112131415161718192021222324252627282930

在这里插入图片描述

4.CallerRunsPolicy()

如果任务被拒绝了,则由调用线程(提交任务的线程)直接执行此任务。

import java.util.concurrent.*;

/**
 * 手动方式创建线程池
 */
public class ThreadPoolDemo10 {
    public static void main(String[] args) {
        ThreadFactory factory=new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread=new Thread(r);
                return thread;
            }
        };
        ThreadPoolExecutor executor=new ThreadPoolExecutor(2,2,10,
                TimeUnit.SECONDS,new LinkedBlockingDeque<>(2),factory,new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < 5; i++) {
            int finalI=i;
            executor.submit(()->{
                try {
                    Thread.sleep(10*finalI);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("任务:"+finalI);
            });
        }
    }
}

123456789101112131415161718192021222324252627282930

在这里插入图片描述

5.自定义拒绝策略

除了上面四种JDK提供的拒绝策略外,我们还可以自定义拒绝策略,具体实现:

import java.util.concurrent.*;

/**
 * 手动方式创建线程池
 */
public class ThreadPoolDemo10 {
    public static void main(String[] args) {
        ThreadFactory factory=new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread=new Thread(r);
                return thread;
            }
        };
        //自定义拒绝策略
        ThreadPoolExecutor executor=new ThreadPoolExecutor(2, 2, 10,
                TimeUnit.SECONDS, new LinkedBlockingDeque<>(2), factory, new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.out.println("我执行了自定义拒绝策略");
            }
        });
        for (int i = 0; i < 5; i++) {
            int finalI1 = i;
            executor.submit(()->{
                try {
                    Thread.sleep(100*finalI1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("任务名:"+Thread.currentThread().getName());
            });
        }
    }
}

123456789101112131415161718192021222324252627282930313233343536

在这里插入图片描述

五、线程池的状态

在这里插入图片描述可以看到线程池的状态共有5种,分别为:

  • RUNNING:线程池创建之后的状态,这种状态下可以执行任务;
  • SHUTDOWN:该状态下线程池不再接受新任务,但是会将工作队列中的任务执行结束;
  • STOP:该状态下线程池不再接受新任务,并且会中断线程;
  • TIDYING:该状态下所有任务都已终止,将会执行terminated方法;
  • TEIMINATED:执行完terminated方法之后。

5.1 Shutdown VS ShutdownNow

  • shutdown执行时线程池终止接收新任务,并且会将任务队列中的任务处理完;
  • shutdoNow执行时线程池终止接收新任务,并且会终止执行任务队列中的任务。

标签:Thread,七种,池看,任务,线程,new,执行,public
From: https://www.cnblogs.com/javaxubo/p/17498423.html

相关文章

  • Android的进程,线程模型
    Android包括一个应用程序框架、几个应用程序库和一个基于Dalvik虚拟机的运行时,所有这些都运行在Linux内核之上。通过利用Linux内核的优势,Android得到了大量操作系统服务,包括进程和内存管理、网络堆栈、驱动程序、硬件抽象层、安全性等相关的服务。 有关Java虚拟机跟进程,线......
  • 腾讯Android岗三面:EventBus 发送的消息,如何做到线程切换?
    一.前言EventBus是一个基于观察者模式的事件订阅/发布框架,利用EventBus可以在不同模块之间,实现低耦合的消息通信。EventBus因为其使用简单且稳定,被广泛应用在一些生产项目中。通常我们就是使用EventBus分发一些消息给消息的订阅者,除此之外我们还可以通过EventBus将消息传......
  • AndroidUI进阶-为什么不能在子线程更新UI
    为什么不能在子线程更新UIandroid.view.ViewRootImpl$CalledFromWrongThreadException:Onlytheoriginalthreadthatcreatedaviewhierarchycantouchitsviews.atandroid.view.ViewRootImpl.checkThread(ViewRootImpl.java:8798)atandroid.view.ViewR......
  • 线程复习
    2023/6/22线程的使用,基础知识,总结复习,后续慢慢补充特点Linux同样用task_struct来描述一个线程,线程和进程都参与统一调度线程共享该进程的地址空间线程是系统调度的最小单位,进程是资源分配的最小单位。线程通信简单,全局变量可以实现,但是需要考虑临界资源保护问题基础函......
  • 字节二面:如何应对Framework层中多进程和线程通信场景
    如果有人问:“在当下环境中,什么样的安卓程序员,不容易被淘汰?”我的答案是:“底层开发!”互联网行业,更新迭代非常快,目前Android底层的架构也在不断调整和优化中,这说明目前的不是最优解,而Android更新迭代了这么多版本,需要兼容旧版本,有些地方不能完全放开去设计,需要在兼容和完全优化中做选......
  • Java—多线程
    ......
  • java中synchronized和ReentrantLock的加锁和解锁能在不同线程吗?如果能,如何实现?
    java中synchronized和ReentrantLock的加锁和解锁能在不同线程吗?如果能,如何实现?答案2023-06-21:java的:这个问题,我问了一些人,部分人是回答得有问题的。synchronized这是个关键字,加锁和解锁不是直接用代码实现,所以在代码层面上就杜绝了加锁和解锁不在同一个线程得情况。可以这么说,synch......
  • java中synchronized和ReentrantLock的加锁和解锁能在不同线程吗?如果能,如何实现?
    java中synchronized和ReentrantLock的加锁和解锁能在不同线程吗?如果能,如何实现?答案2023-06-21:java的:这个问题,我问了一些人,部分人是回答得有问题的。synchronized这是个关键字,加锁和解锁不是直接用代码实现,所以在代码层面上就杜绝了加锁和解锁不在同一个线程得情况。可以这么说,s......
  • 并行计算中的线程和进程:原理与实践
    目录1.引言2.技术原理及概念2.1基本概念解释2.2技术原理介绍3.实现步骤与流程3.1准备工作:环境配置与依赖安装3.2核心模块实现3.3集成与测试4.应用示例与代码实现讲解4.1应用场景介绍4.2应用实例分析4.3核心代码实现4.4代码讲解说明5.优化与改进5.1性能优化并行计算......
  • springboot 默认配置的线程池
     线程池的大小通常都是我们比较关注的,SpringBoot会为系统做默认配置。如果不清楚SpringBoot默认配置的线程池的大小的话,容易线上踩坑。最近碰到一个生产问题,线上部署6台机器,定时任务A,B都在17:00执行,执行时会各自先获取分布式锁。(服务器时间是一致的)理论上是可以做到同......