Java五大线程池

Java五大线程池

线程池概述

核心属性

  • threadFactory : 线程工厂,用于创建线程的工厂
  • corePoolSize : 核心线程数,当线程池运行的线程少于 corePoolSize 时,将创建一个新线程来处理请求,即使其他工作线程处于空闲状态。核心线程也是当新任务到达时才创建和启动。如果想要提前启动一个核心线程,可以使用prestartCoreThread(启动一个核心线程)或 prestartAllCoreThreads(启动全部核心线程)
  • workQueue : 工作队列,用于保留任务并移交给工作线程的阻塞队列。
  • maximumPoolSize : 最大线程数,线程池最多可创新的线程数量
  • handler : 拒绝策略,往线程池添加任务时,将在下面两种情况触发拒绝策略:
    • 线程池运行状态不是 RUNNING;
    • 线程池已经达到最大线程数,并且阻塞队列已满时
  • keepAliveTime : 线程空闲存活时间,如果线程池当前线程数量超过corePoolSize,多余的线程空闲时间超过keepAliveTime就会被终止。

图片摘自程序员囧辉

线程池工作流程

线程池工作流程

  • RUNNING : 运行中,接收新任务,并处理排队任务
  • SHUTDOWN :关闭线程池,不再接收新任务,并处理排队任务
  • STOP :停止线程池,不接受新任务,不处理排队任务
  • TIDYING :所有任务都已终止,到这个状态的时候将会执行terminated 钩子方法
  • TERMINATED : 终止状态。terminated () 已完成

常见的阻塞队列

  • ArrayBlockingQueue:基于数组结构的有界阻塞队列,按先进先出对元素进行排序
  • LinkedBlockingQueue:基于链表结构的有界/无界阻塞队列,按先进先出对元素进行排序,吞吐量通常高于 ArrayBlockingQueueExecutors.newFixedThreadPool 使用了该队列。
  • SynchronousQueue:它其实并不是一个真正的队列,因为它内部没有容器,它是一种配对消费的机制。一个生产线程,当它生产产品(即put的时候),如果当前没有人想要消费产品(即当前没有线程执行take),此生产线程必须阻塞,等待一个消费线程调用take操作,take操作将会唤醒该生产线程,同时消费线程会获取生产线程的产品(即数据传递),这样的一个过程称为一次配对过程(当然也可以先take后put,原理是一样的)。
  • PriorityBlockingQueue:具有优先级无界队列,按优先级对元素进行排序。元素的优先级是通过自然顺序Comparator 来定义的
队列使用注意点
  • 使用有界队列时,需要注意线程池满了后,被拒绝的任务如何处理。
  • 使用无界队列时,需要注意如果任务的提交速度大于线程池的处理速度,可能会导致内存溢出。

拒绝策略

  • AbortPolicy:中止策略。默认的拒绝策略,用户可以捕获异常 手动处理。
  • DiscardPolicy:抛弃策略,直接抛弃任务
  • DiscardOldestPolicy:抛弃最老策略,抛弃阻塞队列中最老的任务。如果是个优先队列,那么意味着抛弃优先级最高的任务,所以最好不要将该策略和优先队列一起使用。
  • CallerRunsPolicy:调用者运行策略。在调用者线程中执行该任务。该策略实现了一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将任务回退到调用者(调用线程池执行任务的主线程),由于执行任务需要一定时间,因此主线程至少在一段时间内不能提交任务,从而使得线程池有时间来处理完正在执行的任务。

newCachedThreadPool

一个可缓存线程池

构造方法

public static ExecutorService newCachedThreadPool()

先来看看jdk8官方的描述。

Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks. Calls to execute will reuse previously constructed threads if available. If no existing thread is available, a new thread will be created and added to the pool. Threads that have not been used for sixty seconds are terminated and removed from the cache. Thus, a pool that remains idle for long enough will not consume any resources. Note that pools with similar properties but different details (for example, timeout parameters) may be created using ThreadPoolExecutor constructors
创建一个线程池,该线程池根据需要创建新线程,但在前面构建的线程可用时将重用它们。这些池通常会提高执行许多短期异步任务的程序的性能。要执行的线程将重用先前构造的线程(如果可用的话)。如果没有可用的现有线程,将创建一个新线程并添加到池中。超过60秒未使用的线程将被终止并从缓存中删除。注意,可以使用ThreadPoolExecutor构造函数创建具有相似属性但不同细节(例如,超时参数)的池。

public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory)

与上面类似,提供了自定义的ThreadFactory线程实现。

参数
/** 
  * @param corePoolSize 池中保留的线程数
  * @param maximumPoolSize 池中允许的最大线程数
  * @param keepAliveTime 空闲线程存活时间
  * @param unit 时间单位
  * @param workQueue 工作队列
  * /
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

// 多了一个 ThreadFactory 
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory){
	return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>(),
                                      threadFactory);
}

可以看到 newCachedThreadPool 的容量可以无限大,且使用了SynchronousQueue (同步队列,这是一个难点,有兴趣可以自行查看一番)

使用案例

@Test
public void test01(){
	// 创建缓存线程池
    ExecutorService service = Executors.newCachedThreadPool();
    int count = 20;
    // countdownlatch 的作用是等待子线程都完成 在进行下一步操作
    CountDownLatch countDownLatch = new CountDownLatch(count);
    for (int i = 0; i < count; i++) {
        int finalI = i;
        service.execute(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" : "+ finalI);
                countDownLatch.countDown();
            }
        });
    }
    countDownLatch.await();
    System.out.println("service:"+service);
    service.shutdown();
}

结果输出:

service:[Shutting down, pool size = 13, active threads = 0, queued tasks = 0, completed tasks = 20]
// pool size: 池子中的线程数 
// active threads: 活动的线程
// queued tasks: 队列任务
// completed tasks: 完成的任务数

特点总结

  • 它可以无限扩大
  • 适合处理任务量大且执行时间较小的任务
  • keepAliveTime为60S,意味着线程空闲时间超过60S就会被杀死
  • 采用SynchronousQueue装等待的任务,这个阻塞队列没有存储空间,这意味着只要有请求到来,就必须要找到一条工作线程处理他,如果当前没有空闲的线程,那么就会再创建一条新的线程。

newFixedThreadPool

一个固定长度的线程池

构造方法

public static ExecutorService newFixedThreadPool(int nThreads)

Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. At any point, at most nThreads threads will be active processing tasks. If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available. If any thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks. The threads in the pool will exist until it is explicitly shutdown.
创建一个线程池,该线程池重用无界队列操作的固定数量的线程。在任何时候,大多数nThreads线程都将是正在处理任务的活动线程。如果在所有线程都处于活动状态时提交了额外的任务,那么它们将在队列中等待,直到有线程可用。如果任何线程在关闭之前的执行过程中由于失败而终止,那么如果需要执行后续任务,一个新的线程将取代它池中的线程将一直存在,直到显式地关闭

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory)

同上 不在累述。

参数
/** 
  * @param corePoolSize 池中保留的线程数
  * @param maximumPoolSize 池中允许的最大线程数
  * @param keepAliveTime 空闲线程存活时间
  * @param unit 时间单位
  * @param workQueue 工作队列
  * /
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>(),
                                  threadFactory);

可以看到newFixedThreadPool 的corePoolSize和maximumPoolSize 都为用户指定。队列采用LinkedBlockingQueue,一个由链表实现的无界阻塞队列。

使用案例

@Test
void test01() throws InterruptedException {
    ExecutorService service = Executors.newFixedThreadPool(10);
    CountDownLatch countDownLatch = new CountDownLatch(5);
    // 可以适当调整循环次数发现:当循环次数(也就是线程数量)<用户设定的nThreads时 ,pool size 为线程数量;
    // 当循环次数(也就是线程数量)>=用户设定的nThreads时 ,pool size 为nThreads;
    for (int i = 0; i < 15; i++) {
        int finalI = i;
        service.execute(()->{
            System.out.println(Thread.currentThread().getName()+" : "+ finalI);
        });
        countDownLatch.countDown();
    }
    countDownLatch.await();
    System.out.println(service);
    service.shutdown();
}

结果

[Running, pool size = 10, active threads = 4, queued tasks = 4, completed tasks = 6]

特点总结

  • 它是一种固定大小的线程池
  • corePoolSizemaximunPoolSize都为用户设定的线程数量nThreads
  • 阻塞队列采用了LinkedBlockingQueue,它是一个无界队列,因此永远不可能拒绝任务。
  • 由于采用了无界队列,实际线程数量将永远维持在nThreads,但是 pool size < nThreads : 创建的线程数 ? nThreads

newScheduledThreadPool

构造方法

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.
创建一个线程池,该线程池可以调度命令在给定延迟后运行或定期执行

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize,ThreadFactory threadFactory)

Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically
创建一个线程池,该线程池可以调度命令在给定延迟后运行或定期执行

四个核心方法

/**
 * 只执行一次的任务
 * @Param command:需要执行的任务
 * @param delay:任务执行前 等待的时间
 * @param unit:时间单位
 */
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);
/**
 * @Param command:需要执行的任务
 * @param initialDely:第一次执行任务 延迟的时间
 * @param period 两次任务间的时间间隔
 * @param unit:时间单位
 */
// scheduleAtFixedRate:如果执行时间超过 设定的时间间隔,则会等上一个任务执行完成 再去执行新的任务
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);

使用案例

schedule

public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);
public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit);
两个方法类似 这里按上面的来介绍

// 注意:这里测试得用main方法 不能像上面一样用 @Test 方法
public static void main(String[] args) throws InterruptedException {
    // 创建线程池
    ScheduledExecutorService  service = Executors.newScheduledThreadPool(5);
    Queue<String> queue = new ConcurrentLinkedQueue<String>();
    for (int i = 0; i < 10; i++) {
        queue.add("queue"+i);
    }
    for (int i = 0; i < queue.size(); i++) {
        final String value = queue.poll();
        service.schedule(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                System.out.println(System.currentTimeMillis()+" : "+value);
            }
        // 表示延时5秒后执行
        },5,TimeUnit.SECONDS);
    }
    // 关闭线程池(一定要关闭线程,否则会一直执行下去)
    service.shutdown();
}

结果

1617759160339 : queue2
1617759160339 : queue0
1617759160339 : queue1
1617759160339 : queue3
1617759160339 : queue4
scheduleAtFixedRate
public static void main(String[] args) throws InterruptedException {
    // 创建线程
    ScheduledExecutorService  service = Executors.newScheduledThreadPool(5);
    Queue<String> queue = new ConcurrentLinkedQueue<String>();
    for (int i = 0; i < 10; i++) {
        queue.add("queue"+i);
    }
    // 这里循环次数注意,为了更好的演示效果 每次执行两条
    for (int i = 0; i < 2; i++) {
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                if(queue.isEmpty()){
                    // 关闭线程池应该由条件控制
                    service.shutdown();
                }else{
                    System.out.println(System.currentTimeMillis()+" : "+queue.poll());
                }
            }
        // 延时5秒启动,每个任务间隔2秒
        },5,2,TimeUnit.SECONDS);
    }
	// 这里不能直接关闭线程池,否则会直接运行到这里 中止所有任务
    // service.shutdown();
}

结果

1617759420040 : queue0
1617759420040 : queue1
1617759422035 : queue2
1617759422035 : queue3
1617759424034 : queue4
1617759424051 : queue5
1617759426035 : queue6
1617759426035 : queue7
1617759428040 : queue8
1617759428040 : queue9
scheduleWithFixedDelay
public static void main(String[] args) throws InterruptedException {
    ScheduledExecutorService  service = Executors.newScheduledThreadPool(5);
    Queue<String> queue = new ConcurrentLinkedQueue<String>();
    for (int i = 0; i < 10; i++) {
        queue.add("queue"+i);
    }
    for (int i = 0; i < 2; i++) {
        service.scheduleWithFixedDelay(() -> {
            if(queue.isEmpty()){
            	// 关闭线程池应该由条件控制
                service.shutdown();
            }else{
                System.out.println(System.currentTimeMillis()+" : "+queue.poll());
            }
        },2,3,TimeUnit.SECONDS);
    }
    // service.shutdown();
}

结果

1617759950326 : queue0
1617759950326 : queue1
1617759953356 : queue2
1617759953356 : queue3
1617759956380 : queue4
1617759956380 : queue5
1617759959414 : queue6
1617759959414 : queue7
1617759962439 : queue8
1617759962439 : queue9

从结果来看可能看不出scheduleWithFixedDelayscheduleAtFixedRate 的区别。下面就讲讲这俩方法的区别

scheduleAtFixedRate 和 scheduleWithFixedDelay 的区别
  • scheduleAtFixedRate优先保证任务执行的频率,但是如果任务执行时间超过了任务间隔时间,则会等待前一个任务执行完成,再去执行下一个任务。例如高铁,每10个小时一班次,过时不候;但如果前面的车次晚点,那么会等待前面的车次,并不会超上前面的车次。
  • scheduleWithFixedDelay : 优先保证时间的间隔。例如,打游戏 游戏时间不固定,但每两局游戏间隔时间固定;打LOL:第一局 30分钟 ,休息10分钟;第二局50分钟,休息10分钟…。无论任务执行时间多长,都会在第一个任务执行完,延迟指定时间后,再去执行第二个任务。

特点总结

  • 采用DelayQueue(无界队列)存储等待的任务
  • DelayQueue内部封装了一个PriorityQueue,它会根据time的先后时间排序,若time相同则根据sequenceNumber排序
  • 工作线程会从DelayQueue取已经到期的任务去执行;执行结束后重新设置任务的到期时间,再次放回DelayQueue

newSingleThreadExecutor

构造方法

public static ExecutorService newSingleThreadExecutor()

Creates an Executor that uses a single worker thread operating off an unbounded queue. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time. Unlike the otherwise equivalent newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.
创建一个执行器,该执行器使用单个工作线程操作一个无界队列。(但是请注意,如果这个单线程在关闭之前的执行过程中由于失败而终止,如果需要执行后续任务,一个新的线程将取代它。) 保证任务按顺序执行,并且在任何给定时间不会有超过一个任务处于活动状态。与等价的newFixedThreadPool(1)不同,返回的执行器保证不会被重新配置以使用其他线程

public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory)

Creates an Executor that uses a single worker thread operating off an unbounded queue, and uses the provided ThreadFactory to create a new thread when needed. Unlike the otherwise equivalent newFixedThreadPool(1, threadFactory) the returned executor is guaranteed not to be reconfigurable to use additional threads
创建一个Executor,该Executor使用单个工作线程操作一个无界队列,并在需要时使用提供的ThreadFactory创建一个新线程。与等价的newFixedThreadPool(1, threadFactory)不同,返回的执行器保证不会被重新配置以使用其他线程

使用案例

@Test
void testSingleTest(){
    ExecutorService service = Executors.newSingleThreadExecutor();
    for (int i = 0; i < 10; i++) {
        service.submit(()->{
            String name = Thread.currentThread().getName();
            System.out.println(name);
        });
    }
    service.shutdown();
}

@Test
void testSingleTest(){
    ExecutorService service = Executors.newSingleThreadExecutor();
    for (int i = 0; i < 10; i++) {
        service.execute(new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                System.out.println(name);
            }
        });
    }
    service.shutdown();
}

结果:

以上两种输出一致,全为 
pool-1-thread-1
也验证了单例的正确性

特点总结

  • 单例线程池,不代表他只会创建一个线程,在任务失败而终止的时候,会创建新的线程取代它。
  • 保证所有任务都会按顺序执行(FIFO,LIFO,优先级等)。
  • 使用无界队列实现阻塞

newWorkStealingPool

public static ExecutorService newWorkStealingPool()

使用所有 available processors作为其目标并行级别创建一个工作窃取线程池

public static ExecutorService newWorkStealingPool(int parallelism)

创建一个维护足够的线程以支持给定的并行级别的线程池,并且可以使用多个队列来减少争用。 并行级别对应于主动参与或可以从事任务处理的最大线程数。 线程的实际数量可以动态增长和收缩。 工作窃取池不保证执行提交的任务的顺序

2个构造



public static ExecutorService newWorkStealingPool() {
    return new ForkJoinPool
        (Runtime.getRuntime().availableProcessors(),
         ForkJoinPool.defaultForkJoinWorkerThreadFactory,
         null, true);
}
/**
 * Creates a thread pool that maintains enough threads to support
 * the given parallelism level, and may use multiple queues to
 * reduce contention. The parallelism level corresponds to the
 * maximum number of threads actively engaged in, or available to
 * engage in, task processing. The actual number of threads may
 * grow and shrink dynamically. A work-stealing pool makes no
 * guarantees about the order in which submitted tasks are
 * executed.
 *
 * @param parallelism the targeted parallelism level 并行级别
 * @return the newly created thread pool
 * @throws IllegalArgumentException if {@code parallelism <= 0}
 * @since 1.8
 */   
public static ExecutorService newWorkStealingPool(int parallelism) {
    return new ForkJoinPool
        (parallelism,
         ForkJoinPool.defaultForkJoinWorkerThreadFactory,
         null, true);
}

特点

  • 并行的线程池,可以传入一个并行度;
  • 不会保证线程执行的顺序,抢占式的工作。

使用案例

@Test
public void test07(){
    ExecutorService pool = Executors.newWorkStealingPool();
    for (int i = 0; i < 10; i++) {
        int finalI = i;
        pool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " : "+ finalI);
            }
        });
    }
}

@Test
public void test08(){
    // 设置并发量
    ExecutorService pool = Executors.newWorkStealingPool(2);
    for (int i = 0; i < 10; i++) {
        int finalI = i;
        pool.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " : "+ finalI);
            }
        });
    }
}

结果

//第一段程序的结果:
ForkJoinPool-1-worker-1 : 0
ForkJoinPool-1-worker-2 : 1
ForkJoinPool-1-worker-1 : 3
ForkJoinPool-1-worker-1 : 6
ForkJoinPool-1-worker-1 : 7
ForkJoinPool-1-worker-3 : 2
ForkJoinPool-1-worker-1 : 8
ForkJoinPool-1-worker-3 : 9
ForkJoinPool-1-worker-2 : 4
ForkJoinPool-1-worker-4 : 5
//第二段:只创建了2个线程
ForkJoinPool-1-worker-0 : 1
ForkJoinPool-1-worker-1 : 0
ForkJoinPool-1-worker-0 : 2
ForkJoinPool-1-worker-1 : 3
ForkJoinPool-1-worker-0 : 4
ForkJoinPool-1-worker-1 : 5
ForkJoinPool-1-worker-0 : 6
ForkJoinPool-1-worker-1 : 7
ForkJoinPool-1-worker-0 : 8
ForkJoinPool-1-worker-1 : 9

补充:submit 和 execute

在上述使用过程中 想必大家都有发现 线程都有这两个执行方法;简单来讲就是

  • submit有返回值 类型为 Future<?> ; execute 没有返回值。可以用Future来捕获错误信息。

补充:自定义线程池

上面所有的线程池都是 Executors 创建出来的;再往底层看可以看到 每种线程池实际都是new了一个ThreadPoolExecutor的对象,传入了不同的参数而已。

/**
 * Creates a new {@code ThreadPoolExecutor} with the given initial
 * parameters and default thread factory and rejected execution handler.
 * It may be more convenient to use one of the {@link Executors} factory
 * methods instead of this general purpose constructor.
 *
 * @param corePoolSize 核心线程池
 * @param maximumPoolSize 池中允许的最大线程数
 * @param keepAliveTime 空闲线程存活时间
 * @param unit 时间单位
 * @param workQueue 工作队列
 */
ThreadPoolExecutor(int corePoolSize,
                       int maximumPoolSize,
                       long keepAliveTime,
                       TimeUnit unit,
                       BlockingQueue<Runnable> workQueue)

我们也可以自定义一个线程池

static class Myclass implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

@Test
public void test05(){
	// 数组实现的阻塞队列
    BlockingQueue<Runnable> bq = new ArrayBlockingQueue<>(10);
    // 自定义线程池 核心线程数为2 最大线程数为3 空闲线程存活时间60s
    ThreadPoolExecutor executor = new ThreadPoolExecutor(2,3,60,TimeUnit.SECONDS,bq);
    Runnable r1 = new Myclass();
    Runnable r2 = new Myclass();
    Runnable r3 = new Myclass();
    executor.execute(r1);
    executor.execute(r2);
    executor.execute(r3);
    executor.shutdown();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SpringCloud的五大核心组件如下: 1. Eureka:服务注册与发现组件,提供了服务注册和发现的功能,可以实现服务的自动化注册和发现。 2. Feign:声明式的Web Service客户端,可以让编写Web Service客户端更加简单。 3. Ribbon:客户端负载均衡器,可以在多个服务提供者之间进行负载均衡。 4. Hystrix:容错管理工具,可以实现服务的降级、熔断、限流等功能,提高系统的可用性。 5. Zuul:网关组件,可以实现请求的路由、过滤、转发等功能,提高系统的安全性和可用性。 以下是SpringCloud五大组件的简要介绍: 1. Eureka:Eureka是Netflix开源的一款基于REST的服务治理解决方案,主要用于AWS云中定位服务,以实现中间层服务器的负载均衡和故障转移。Eureka包含两个组件:Eureka Server和Eureka Client。Eureka Server提供服务注册和发现功能,Eureka Client是一个Java客户端,用于简化与Eureka Server的交互。 2. Feign:Feign是一个声明式的Web Service客户端,可以让编写Web Service客户端更加简单。Feign支持多种注解,包括FeignClient、RequestMapping、PathVariable、RequestParam等,可以方便地定义和调用Web Service接口。 3. Ribbon:Ribbon是一个客户端负载均衡器,可以在多个服务提供者之间进行负载均衡。Ribbon支持多种负载均衡策略,包括轮询、随机、加权轮询、加权随机等,可以根据实际情况选择合适的负载均衡策略。 4. Hystrix:Hystrix是一个容错管理工具,可以实现服务的降级、熔断、限流等功能,提高系统的可用性。Hystrix通过线程池隔离、断路器、请求缓存等机制来实现容错管理,可以有效地防止服务雪崩效应。 5. Zuul:Zuul是一个网关组件,可以实现请求的路由、过滤、转发等功能,提高系统的安全性和可用性。Zuul支持多种路由策略,包括基于URL路径、基于服务名称、基于请求参数等,可以根据实际情况选择合适的路由策略。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值