java8阻止_如何在Java 8中创建阻止后台加载程序? - java

如何在Java 8中创建适当的后台加载程序?条件:

数据应在后台加载

加载后应显示数据

加载数据时,不应接受其他任何请求

如果在加载数据时有请求,则应在一定的超时时间(例如5秒)后安排另一次加载

目的是为了。 G。已接受了重载请求,但数据库中没有大量请求。

MCVE

这是MCVE。它由一个后台任务组成,该任务通过简单地调用Thread.sleep 2秒钟来模拟加载。每秒安排一次任务,这自然会导致后台加载任务重叠,因此应避免。

public class LoadInBackgroundExample {

/**

* A simple background task which should perform the data loading operation. In this minimal example it simply invokes Thread.sleep

*/

public static class BackgroundTask implements Runnable {

private int id;

public BackgroundTask(int id) {

this.id = id;

}

/**

* Sleep for a given amount of time to simulate loading.

*/

@Override

public void run() {

try {

System.out.println("Start #" + id + ": " + Thread.currentThread());

long sleepTime = 2000;

Thread.sleep( sleepTime);

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

System.out.println("Finish #" + id + ": " + Thread.currentThread());

}

}

}

/**

* CompletableFuture which simulates loading and showing data.

* @param taskId Identifier of the current task

*/

public static void loadInBackground( int taskId) {

// create the loading task

BackgroundTask backgroundTask = new BackgroundTask( taskId);

// "load" the data asynchronously

CompletableFuture completableFuture = CompletableFuture.supplyAsync(new Supplier() {

@Override

public String get() {

CompletableFuture future = CompletableFuture.runAsync(backgroundTask);

try {

future.get();

} catch (InterruptedException | ExecutionException e) {

e.printStackTrace();

}

return "task " + backgroundTask.id;

}

});

// display the data after they are loaded

CompletableFuture future = completableFuture.thenAccept(x -> {

System.out.println( "Background task finished:" + x);

});

}

public static void main(String[] args) {

// runnable which invokes the background loader every second

Runnable trigger = new Runnable() {

int taskId = 0;

public void run() {

loadInBackground( taskId++);

}

};

// create scheduler

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

ScheduledFuture> beeperHandle = scheduler.scheduleAtFixedRate(trigger, 0, 1, TimeUnit.SECONDS);

// cancel the scheudler and the application after 10 seconds

scheduler.schedule(() -> beeperHandle.cancel(true), 10, TimeUnit.SECONDS);

try {

beeperHandle.get();

} catch (Throwable th) {

}

System.out.println( "Cancelled");

System.exit(0);

}

}

输出是这样的:

Start #0: Thread[ForkJoinPool.commonPool-worker-2,5,main]

Start #1: Thread[ForkJoinPool.commonPool-worker-4,5,main]

Start #2: Thread[ForkJoinPool.commonPool-worker-6,5,main]

Finish #0: Thread[ForkJoinPool.commonPool-worker-2,5,main]

Background task finished:task 0

Finish #1: Thread[ForkJoinPool.commonPool-worker-4,5,main]

Background task finished:task 1

Start #3: Thread[ForkJoinPool.commonPool-worker-4,5,main]

Finish #2: Thread[ForkJoinPool.commonPool-worker-6,5,main]

Background task finished:task 2

Start #4: Thread[ForkJoinPool.commonPool-worker-6,5,main]

Start #5: Thread[ForkJoinPool.commonPool-worker-2,5,main]

Finish #3: Thread[ForkJoinPool.commonPool-worker-4,5,main]

Background task finished:task 3

Start #6: Thread[ForkJoinPool.commonPool-worker-4,5,main]

Finish #4: Thread[ForkJoinPool.commonPool-worker-6,5,main]

Background task finished:task 4

Finish #5: Thread[ForkJoinPool.commonPool-worker-2,5,main]

Background task finished:task 5

Start #7: Thread[ForkJoinPool.commonPool-worker-2,5,main]

Finish #6: Thread[ForkJoinPool.commonPool-worker-4,5,main]

Start #8: Thread[ForkJoinPool.commonPool-worker-6,5,main]

Background task finished:task 6

Start #9: Thread[ForkJoinPool.commonPool-worker-4,5,main]

Finish #7: Thread[ForkJoinPool.commonPool-worker-2,5,main]

Background task finished:task 7

Start #10: Thread[ForkJoinPool.commonPool-worker-2,5,main]

Finish #8: Thread[ForkJoinPool.commonPool-worker-6,5,main]

Background task finished:task 8

Cancelled

目标是拥有e。 G。 #1和#2被跳过,因为#0仍在运行。

问题

您在哪里正确设置阻止机制?应该使用同步吗?还是一些AtomicBoolean?如果是这样,它应该在get()方法内部还是其他位置?

参考方案

您已经有一个线程池来执行任务。

在另一个异步执行器(使用ForkJoinPool时,使用CompletableFuture)运行任务并不一定很复杂。

简单点:

public static void loadInBackground(int taskId) {

// create the loading task

BackgroundTask backgroundTask = new BackgroundTask(taskId);

// No need to run in async, as it already in executor

backgroundTask.run();

}

当您使用scheduleAtFixedRate调用ScheduledExecutorService时,将确保一次仅运行一项任务

创建并执行一个周期性操作,该操作在给定的初始延迟后首先启用,然后在给定的时间段内启用;也就是说,执行将在initialDelay,initialDelay + period,initialDelay + 2 * period等之后开始。如果任务的任何执行遇到异常,则将禁止后续执行。否则,任务将仅通过取消或终止执行程序而终止。如果此任务的任何执行花费的时间超过其周期,则后续执行可能会延迟开始,但不会同时执行。

如何在Java swing中对jComboBox元素进行排序? - java

如何将jComboBox元素列表排序为排序列表。JComboBox box=new JComboBox(); box.addItem("abc"); box.addItem("zzz"); box.addItem("ccc"); add(box); 我使用了许多jComboBox组件,但无法正常工作…如何在Java 11(或更高版本)中启动单文件程序? - java

JEP 330描述了JDK 11中用于在Java中启动单文件程序的一项新功能。我试过了:$ ./Example.java但这不起作用。正确的用法是什么? 参考方案 精简版:$ java Example.java data.txt 或(使用#!):$ ./example data.txt 细节:工作示例here。考虑一个单文件程序来打印文件中的行:import…如何在Java dom解析器中格式化xml? - java

<?xml version="1.0" encoding="UTF-8"?> 在这里,第一个标签被写入文件,然后是xml版本,我需要在下一行中编写。像下面<?xml version="1.0" encoding="UTF…JAVA:字节码和二进制有什么区别? - java

java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…java:继承 - java

有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页