[Alta concurrencia] No cause problemas, ¿no comprende la diferencia entre ScheduledThreadPoolExecutor y Timer?

Hola a todos, soy Glacier~~

JDK 1.5 comenzó a proporcionar la clase ScheduledThreadPoolExecutor.La clase ScheduledThreadPoolExecutor hereda la clase ThreadPoolExecutor y reutiliza el grupo de subprocesos para implementar la función de programación periódica de tareas. Antes de JDK 1.5, las clases Timer y TimerTask se usaban principalmente para implementar la programación periódica de tareas. Este artículo presenta brevemente la diferencia entre la clase ScheduledThreadPoolExecutor y la clase Timer, cuáles son las ventajas de la clase ScheduledThreadPoolExecutor en comparación con la clase Timer y un ejemplo simple de cómo las dos implementan la programación de tareas respectivamente.

La diferencia entre los dos

ángulo de rosca

  • El temporizador es un modo de subproceso único. Si el tiempo de ejecución de una tarea TimerTask es relativamente largo, afectará la ejecución de la programación de otras tareas.
  • El ScheduledThreadPoolExecutor es un modo de subprocesos múltiples y reutiliza el grupo de subprocesos.La ejecución de una tarea ScheduledFutureTask lleva mucho tiempo y no afectará la ejecución de la programación de otras tareas.

Sensibilidad del tiempo del sistema

  • La programación del temporizador se basa en la hora absoluta del sistema operativo y es sensible a la hora del sistema operativo. Una vez que cambia la hora del sistema operativo, la programación del temporizador ya no es precisa.
  • La programación de ScheduledThreadPoolExecutor se basa en el tiempo relativo y no se ve afectada por los cambios en la hora del sistema operativo.

si capturar excepciones

  • Timer no detectará las excepciones lanzadas por TimerTask, además, Timer es de un solo subproceso. Una vez que se produce una excepción en una tarea programada, se terminará todo el subproceso y ya no se ejecutarán otras tareas que deban programarse.
  • ScheduledThreadPoolExecutor implementa la función de programación basada en el grupo de subprocesos. Después de que una tarea arroja una excepción, otras tareas aún se pueden ejecutar normalmente.

Si la tarea tiene prioridad

  • La tarea TimerTask ejecutada en el Timer no tiene concepto de prioridad como un todo, y solo ejecuta la tarea de acuerdo al tiempo absoluto del sistema.
  • ScheduledThreadPoolExecutor中执行的ScheduledFutureTask类实现了java.lang.Comparable接口和java.util.concurrent.Delayed接口,这也就说明了ScheduledFutureTask类中实现了两个非常重要的方法,一个是java.lang.Comparable接口的compareTo方法,一个是java.util.concurrent.Delayed接口的getDelay方法。在ScheduledFutureTask类中compareTo方法方法实现了任务的比较,距离下次执行的时间间隔短的任务会排在前面,也就是说,距离下次执行的时间间隔短的任务的优先级比较高。而getDelay方法则能够返回距离下次任务执行的时间间隔。

是否支持对任务排序

  • Timer不支持对任务的排序。
  • ScheduledThreadPoolExecutor类中定义了一个静态内部类DelayedWorkQueue,DelayedWorkQueue类本质上是一个有序队列,为需要调度的每个任务按照距离下次执行时间间隔的大小来排序

能否获取返回的结果

  • Timer中执行的TimerTask类只是实现了java.lang.Runnable接口,无法从TimerTask中获取返回的结果。
  • ScheduledThreadPoolExecutor中执行的ScheduledFutureTask类继承了FutureTask类,能够通过Future来获取返回的结果。

通过以上对ScheduledThreadPoolExecutor类和Timer类的分析对比,相信在JDK 1.5之后,就没有使用Timer来实现定时任务调度的必要了。

二者简单的示例

这里,给出使用Timer和ScheduledThreadPoolExecutor实现定时调度的简单示例,为了简便,我这里就直接使用匿名内部类的形式来提交任务。

Timer类简单示例

源代码示例如下所示。

package io.binghe.concurrent.lab09;

import java.util.Timer;
import java.util.TimerTask;

/**
 * @author binghe
 * @version 1.0.0
 * @description 测试Timer
 */
public class TimerTest {

    public static void main(String[] args) throws InterruptedException {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println("测试Timer类");
            }
        }, 1000, 1000);
        Thread.sleep(10000);
        timer.cancel();
    }
}

运行结果如下所示。

测试Timer类
测试Timer类
测试Timer类
测试Timer类
测试Timer类
测试Timer类
测试Timer类
测试Timer类
测试Timer类
测试Timer类

ScheduledThreadPoolExecutor类简单示例

源代码示例如下所示。

package io.binghe.concurrent.lab09;

import java.util.concurrent.*;

/**
 * @author binghe
 * @version 1.0.0
 * @description 测试ScheduledThreadPoolExecutor
 */
public class ScheduledThreadPoolExecutorTest {
    public static void main(String[] args) throws  InterruptedException {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("测试测试ScheduledThreadPoolExecutor");
            }
        }, 1, 1, TimeUnit.SECONDS);

        //主线程休眠10秒
        Thread.sleep(10000);

        System.out.println("正在关闭线程池...");
        // 关闭线程池
        scheduledExecutorService.shutdown();
        boolean isClosed;
        // 等待线程池终止
        do {
            isClosed = scheduledExecutorService.awaitTermination(1, TimeUnit.DAYS);
            System.out.println("正在等待线程池中的任务执行完成");
        } while(!isClosed);

        System.out.println("所有线程执行结束,线程池关闭");
    }
}

运行结果如下所示。

测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
测试测试ScheduledThreadPoolExecutor
正在关闭线程池...
测试测试ScheduledThreadPoolExecutor
正在等待线程池中的任务执行完成
所有线程执行结束,线程池关闭

注意:关于Timer和ScheduledThreadPoolExecutor还有其他的使用方法,这里,我就简单列出以上两个使用示例,更多的使用方法大家可以自行实现。

好了,今天就到这儿吧,我是冰河,我们下期见~~

我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿

Supongo que te gusta

Origin juejin.im/post/7122305721768607775
Recomendado
Clasificación