奇趣5分彩

Java Spring别离完奇趣5分彩按时使命体例

 更新时辰:2022年07月12日 11:56:52   作者:少年.  
这篇文章首要为大师具体先容了Java与Spring设置静态按时使命的体例,按时使命的利用处景很是普遍,如按时清算文件、按时天生报表、按时数据同步备份等

java完奇趣5分彩按时使命

Jdk自带的库奇趣5分彩,奇趣5分彩两种体例能够完奇趣5分彩按时使命,一种是Timer,另外一种是ScheduledThreadPoolExecutor

Timer+TimerTask

建立一个Timer就建立了一个线程,能够用来调剂TimerTask使命

Timer奇趣5分彩四个机关体例,能够指定Timer线程的名字和是不是设置为为保护线程。默许名字Timer-编号,默许不是保护线程。

首要奇趣5分彩三个比拟首要的体例:

cancel():遏制使命调剂,打消今后调剂的一切使命,正在运转的使命不受影响

purge():从使命行列奇趣5分彩移除一切已打消的使命

schedule:起头调剂使命,供给了几个重载体例:

schedule(TimerTask task, long delay)延时履行,表现delay毫秒后履行一次task使命

schedule(TimerTask task, Date time)`指按时辰履行,到`time`时辰的时辰履行一次`task
schedule(TimerTask task, long delay, long period)`延时周期履行,颠末`delay`毫秒后每`period`毫秒履行一次`task
schedule(TimerTask task, Date firstTime, long period)`指按时辰后周期履行,达到指按时辰`firstTime`后每`period`毫秒履行一次`task

示例

public class TimerTest {
    public static void main(String[] args) {
        Timer timer = new Timer("aa");
        Task task = new Task();
        timer.schedule(task,new Date(),1000);
    }
}
class Task extends TimerTask{
    @Override
    public void run() {
        System.out.println(new Date());
    }
}

输入:
Thu Jul 07 14:50:02 CST 2022
Thu Jul 07 14:50:03 CST 2022
Thu Jul 07 14:50:04 CST 2022
Thu Jul 07 14:50:05 CST 2022
…………

弊病

Timer是单线程的,并且不会抛出很是,一旦按时使命抛出很是,将会致使全部线程遏制,即按时使命遏制。

ScheduledThreadPoolExecutor

由于Timer的错误谬误,以是不倡议利用Timer,倡议利用ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutorTimer的替换者,于JDK1.5引入,担当了ThreadPoolExecutor,是基于线程池设想的按时使命类。

首要的调剂体例:

schedule只履行一次调剂,(使命,提早时辰,提早时辰单元)

scheduleAtFixedRate按牢固的频次调剂,若是履行时辰太奇趣5分彩,下次调剂会提早,(使命,第一次履行的提早时辰,周期,时辰单元)

scheduleWithFixedDelay提早调剂,一次使命履行完后加上提早时辰履行下一次使命,(使命,第一次履行的提早时辰,距离时辰,时辰单元)

示例

public class TimerTest {
    public static void main(String[] args) throws Exception{
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
        scheduledExecutorService.scheduleAtFixedRate(
                () -> System.out.println(new Date()),
                1,3, TimeUnit.SECONDS);
    }
}

Spring按时使命

Spring按时使命首要靠@Scheduled表明完奇趣5分彩,corn,fixedDelay,fixedDelayString,fixedRate,fixedRateString五个参数必须指定其一,传两个或三个城市抛出很是

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
	String CRON_DISABLED = ScheduledTaskRegistrar.CRON_DISABLED;
    // cron抒发式
	String cron() default "";
    // 时区
	String zone() default "";
    // 从上一次挪用竣事到下一次挪用之间的固按时辰
	long fixedDelay() default -1;
    // 和fixedDelay意义不异,只是利用字符传格局,撑持占位符。比方:fixedDelayString = "${time.fixedDelay}"
	String fixedDelayString() default "";
    // 两次挪用之间牢固的毫秒数(不须要期待前次使命完奇趣5分彩)
	long fixedRate() default -1;
    // 同上,撑持占位符
	String fixedRateString() default "";
    // 第一次履行使命前提早的毫秒数
	long initialDelay() default -1;
    // 同上,撑持占位符
	String initialDelayString() default "";
}

示例

@Component
@EnableScheduling
public class ScheduledTask {
    @Scheduled(fixedDelay = 1000)
    public void task(){
        System.out.println("aaa");
    }
}

道理

名目启动ScheduledAnnotationBeanPostProcessorpostProcessAfterInitialization()体例扫描带奇趣5分彩@Scheduled表明的体例:

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		if (bean instanceof AopInfrastructureBean || bean instanceof TaskScheduler ||
				bean instanceof ScheduledExecutorService) {
			// Ignore AOP infrastructure such as scoped proxies.
			return bean;
		}
		Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);
		if (!this.nonAnnotatedClasses.contains(targetClass) &&
				AnnotationUtils.isCandidateClass(targetClass, Arrays.asList(Scheduled.class, Schedules.class))) {
			Map<Method, Set<Scheduled>> annotatedMethods = MethodIntrospector.selectMethods(targetClass,
					(MethodIntrospector.MetadataLookup<Set<Scheduled>>) method -> {
						Set<Scheduled> scheduledMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(
								method, Scheduled.class, Schedules.class);
						return (!scheduledMethods.isEmpty() ? scheduledMethods : null);
					});
			if (annotatedMethods.isEmpty()) {
				this.nonAnnotatedClasses.add(targetClass);
				if (logger.isTraceEnabled()) {
					logger.trace("No @Scheduled annotations found on bean class: " + targetClass);
				}
			}
			else {
				// Non-empty set of methods
				annotatedMethods.forEach((method, scheduledMethods) ->
                        // 挪用processScheduled体例将按时使命的体例寄存到使命行列奇趣5分彩
						scheduledMethods.forEach(scheduled -> processScheduled(scheduled, method, bean)));
				if (logger.isTraceEnabled()) {
					logger.trace(annotatedMethods.size() + " @Scheduled methods processed on bean '" + beanName +
							"': " + annotatedMethods);
				}
			}
		}
		return bean;
	}
	protected void processScheduled(Scheduled scheduled, Method method, Object bean) {
		try {
            // 建立使命线程
			Runnable runnable = createRunnable(bean, method);
            // 分解到按时使命体例的标记,分解到准确的参数后会设置为TRUE,若是在分解到了其余的参数就会抛出很是
			boolean processedSchedule = false;
			String errorMessage =
					"Exactly one of the 'cron', 'fixedDelay(String)', or 'fixedRate(String)' attributes is required";
			Set<ScheduledTask> tasks = new LinkedHashSet<>(4);
			// Determine initial delay 分解第一次的提早(分解initialDelay参数)
			long initialDelay = scheduled.initialDelay();
			String initialDelayString = scheduled.initialDelayString();
			if (StringUtils.hasText(initialDelayString)) {
                // initialDelay不能小于0
				Assert.isTrue(initialDelay < 0, "Specify 'initialDelay' or 'initialDelayString', not both");
				if (this.embeddedValueResolver != null) {
					initialDelayString = this.embeddedValueResolver.resolveStringValue(initialDelayString);
				}
				if (StringUtils.hasLength(initialDelayString)) {
					try {
						initialDelay = parseDelayAsLong(initialDelayString);
					}
					catch (RuntimeException ex) {
						throw new IllegalArgumentException(
								"Invalid initialDelayString value \"" + initialDelayString + "\" - cannot parse into long");
					}
				}
			}
			// Check cron expression 分解cron抒发式
			String cron = scheduled.cron();
			if (StringUtils.hasText(cron)) {
                // 分解时区
				String zone = scheduled.zone();
				if (this.embeddedValueResolver != null) {
					cron = this.embeddedValueResolver.resolveStringValue(cron);
					zone = this.embeddedValueResolver.resolveStringValue(zone);
				}
				if (StringUtils.hasLength(cron)) {
					Assert.isTrue(initialDelay == -1, "'initialDelay' not supported for cron triggers");
					processedSchedule = true;
					if (!Scheduled.CRON_DISABLED.equals(cron)) {
						TimeZone timeZone;
						if (StringUtils.hasText(zone)) {
							timeZone = StringUtils.parseTimeZoneString(zone);
						}
						else {
							timeZone = TimeZone.getDefault();
						}
						tasks.add(this.registrar.scheduleCronTask(new CronTask(runnable, new CronTrigger(cron, timeZone))));
					}
				}
			}
            // 第一次提早参数小于0,默许为0
			// At this point we don't need to differentiate between initial delay set or not anymore
			if (initialDelay < 0) {
				initialDelay = 0;
			}
			// Check fixed delay 分解fixedDelay参数
			long fixedDelay = scheduled.fixedDelay();
			if (fixedDelay >= 0) {
				Assert.isTrue(!processedSchedule, errorMessage);
				processedSchedule = true;
				tasks.add(this.registrar.scheduleFixedDelayTask(new FixedDelayTask(runnable, fixedDelay, initialDelay)));
			}
			String fixedDelayString = scheduled.fixedDelayString();
			if (StringUtils.hasText(fixedDelayString)) {
				if (this.embeddedValueResolver != null) {
					fixedDelayString = this.embeddedValueResolver.resolveStringValue(fixedDelayString);
				}
				if (StringUtils.hasLength(fixedDelayString)) {
					Assert.isTrue(!processedSchedule, errorMessage);
					processedSchedule = true;
					try {
						fixedDelay = parseDelayAsLong(fixedDelayString);
					}
					catch (RuntimeException ex) {
						throw new IllegalArgumentException(
								"Invalid fixedDelayString value \"" + fixedDelayString + "\" - cannot parse into long");
					}
					tasks.add(this.registrar.scheduleFixedDelayTask(new FixedDelayTask(runnable, fixedDelay, initialDelay)));
				}
			}
			// Check fixed rate 分解fixedRate参数
			long fixedRate = scheduled.fixedRate();
			if (fixedRate >= 0) {
				Assert.isTrue(!processedSchedule, errorMessage);
				processedSchedule = true;
				tasks.add(this.registrar.scheduleFixedRateTask(new FixedRateTask(runnable, fixedRate, initialDelay)));
			}
			String fixedRateString = scheduled.fixedRateString();
			if (StringUtils.hasText(fixedRateString)) {
				if (this.embeddedValueResolver != null) {
					fixedRateString = this.embeddedValueResolver.resolveStringValue(fixedRateString);
				}
				if (StringUtils.hasLength(fixedRateString)) {
					Assert.isTrue(!processedSchedule, errorMessage);
					processedSchedule = true;
					try {
						fixedRate = parseDelayAsLong(fixedRateString);
					}
					catch (RuntimeException ex) {
						throw new IllegalArgumentException(
								"Invalid fixedRateString value \"" + fixedRateString + "\" - cannot parse into long");
					}
					tasks.add(this.registrar.scheduleFixedRateTask(new FixedRateTask(runnable, fixedRate, initialDelay)));
				}
			}
			// Check whether we had any attribute set
            // 若是五个参数一个也没分解到,抛出很是
			Assert.isTrue(processedSchedule, errorMessage);
			// Finally register the scheduled tasks
            // 并发节制将使命行列存入注册使命列表
			synchronized (this.scheduledTasks) {
				Set<ScheduledTask> regTasks = this.scheduledTasks.computeIfAbsent(bean, key -> new LinkedHashSet<>(4));
				regTasks.addAll(tasks);
			}
		}
		catch (IllegalArgumentException ex) {
			throw new IllegalStateException(
					"Encountered invalid @Scheduled method '" + method.getName() + "': " + ex.getMessage());
		}
	}

将使命分解并增加到使命行列后,交由ScheduledTaskRegistrar类的scheduleTasks体例增加(注册)按时使命到情况奇趣5分彩

protected void scheduleTasks() {
   if (this.taskScheduler == null) {
       //获得ScheduledExecutorService东西,现实上奇趣5分彩是利用ScheduledThreadPoolExecutor履行按时使命调剂
      this.localExecutor = Executors.newSingleThreadScheduledExecutor();
      this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
   }
   if (this.triggerTasks != null) {
      for (TriggerTask task : this.triggerTasks) {
         addScheduledTask(scheduleTriggerTask(task));
      }
   }
   if (this.cronTasks != null) {
      for (CronTask task : this.cronTasks) {
         addScheduledTask(scheduleCronTask(task));
      }
   }
   if (this.fixedRateTasks != null) {
      for (IntervalTask task : this.fixedRateTasks) {
         addScheduledTask(scheduleFixedRateTask(task));
      }
   }
   if (this.fixedDelayTasks != null) {
      for (IntervalTask task : this.fixedDelayTasks) {
         addScheduledTask(scheduleFixedDelayTask(task));
      }
   }
}
private void addScheduledTask(@Nullable ScheduledTask task) {
   if (task != null) {
      this.scheduledTasks.add(task);
   }
}

到此这篇对于Java Spring别离完奇趣5分彩按时使命体例的文章就先容到这了,更多相干Java 按时使命内容请搜刮剧本之奇趣5分彩之前的文章或持续阅读上面的相干文章但愿大师今后多多撑持剧本之奇趣5分彩!

相干文章

最新批评