gpt4 book ai didi

Java:创建一个后台线程来更新变量

转载 作者:行者123 更新时间:2023-12-01 19:40:39 25 4
gpt4 key购买 nike

*Java 新手

在 Main 中,它在迭代 workItems 之前调用 processItems()。问题是 processItems() 需要很长时间,比如 10 分钟

 import java.lang.*;
import java.util.*;
import static java.util.stream.Collectors.*;

public class App {
private List<String> workItems;
private int factor = 0;
public App() {
workItems = new ArrayList<>();
//create some work in workItmes
workItems.add("apple");
workItems.add("oranges");
workItems.add("bananas");
}

public List<String> getWorkItems() {
return workItems;
}

public void calculateFactor() throws Exception{
// does some work which takes a long time
Thread.sleep(5*1000);
factor = 1;
}

public boolean evaluateItem(String item, int factor) {
// do some work based on item and current factor
System.out.println("Received: " + item + " " + factor);
return true;
}

public int getFactor() {
return factor;
}

public static void main(String[] args) throws Exception
{
App myApp = new App();
System.out.println("starting...");
int cnt = 0;
while (true) {
cnt++;
if (cnt > 5) {
break;
}

myApp.calculateFactor(); //<------- I dont want to call this here but in a background thread
int current_factor = myApp.getFactor();
List<Boolean> results = myApp.getWorkItems().stream().map(s -> myApp.evaluateItem(s, current_factor)).collect(toList());
System.out.println(results);
Thread.sleep(1*1000); // sleep a min
}
System.out.println("done");
}
}

我想将 main 中的调用 myApp.calculateFactor() 委托(delegate)给后台线程

有两件事:这个后台线程需要访问 workItems 并更新一个通过 getFactor() 对 main 可见的变量

我正在查看 ExecutorService executorService= Executors.newSingleThreadExecutor(); 但我似乎没有一个教程表明它可以看到线程父级的命名空间。

另外,后台线程的清理会是什么样子?只需调用 shutdown() 即可?它如何处理中断?

最佳答案

您确实可以像这样使用Executors.newSingleThreadExecutor():

public class App {
private List<String> workItems;
private AtomicInteger factor = new AtomicInteger(0);

public App() {
workItems = new ArrayList<>();
//create some work in workItmes
workItems.add("apple");
workItems.add("oranges");
workItems.add("bananas");
}

public List<String> getWorkItems() {
return workItems;
}


public void calculateFactor() throws InterruptedException {
TimeUnit.SECONDS.sleep(5);
factor.set(1);
}

public boolean evaluateItem(String item, int factor) {
// do some work based on item and current factor
System.out.println("Received: " + item + " " + factor);
return true;
}

public AtomicInteger getFactor() {
return factor;
}

public static void main(String[] args) throws Exception {
App myApp = new App();
ExecutorService executorService = Executors.newSingleThreadExecutor();

System.out.println("starting...");
int cnt = 0;
while (true) {
cnt++;
if (cnt > 5) {
break;
}

executorService.submit(() -> {
try {
myApp.calculateFactor();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("Error when calculating Factor");
}
});
int currentFactor = myApp.getFactor().get();
List<Boolean> results = myApp.getWorkItems().stream().map(s -> myApp.evaluateItem(s, currentFactor)).collect(toList());
System.out.println(results);
TimeUnit.SECONDS.sleep(1);
}

executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.SECONDS);
System.out.println("done");
}
}

这里 executorService 将运行一个新的 Runnable,它只运行您的方法calculateFactor。为了确保 factor 正确更新并由主线程并行读取,您可以使用专用于此类工作的 AtomicInteger。关于关闭和中断,最后你应该这样做:

executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.SECONDS); // Time is arbitrary here. It depends your need

参见shutdown and awaitTermination which first call have any difference?了解更多详情。

在您的示例中,当我测试它时,因子不会改变,因为您等待 5 秒,线程calculateFactor 等待 5 秒,所以我的结果是:

starting...
Received: apple 0
Received: oranges 0
Received: bananas 0
[true, true, true]
Received: apple 0
Received: oranges 0
Received: bananas 0
[true, true, true]
Received: apple 0
Received: oranges 0
Received: bananas 0
[true, true, true]
Received: apple 0
Received: oranges 0
Received: bananas 0
[true, true, true]
Received: apple 0
Received: oranges 0
Received: bananas 0
[true, true, true]
done

但是如果我输入 cnt>10 我会得到这个结果:

starting...
Received: apple 0
Received: oranges 0
Received: bananas 0
[true, true, true]
Received: apple 0
Received: oranges 0
Received: bananas 0
[true, true, true]
Received: apple 0
Received: oranges 0
Received: bananas 0
[true, true, true]
Received: apple 0
Received: oranges 0
Received: bananas 0
[true, true, true]
Received: apple 0
Received: oranges 0
Received: bananas 0
[true, true, true]
Received: apple 1
Received: oranges 1
Received: bananas 1
[true, true, true]
Received: apple 1
Received: oranges 1
Received: bananas 1
[true, true, true]
Received: apple 1
Received: oranges 1
Received: bananas 1
[true, true, true]
Received: apple 1
Received: oranges 1
Received: bananas 1
[true, true, true]
Received: apple 1
Received: oranges 1
Received: bananas 1
[true, true, true]

希望能解答您的问题

补充:如果您只想运行一次calculateFactor,您可以使用countDownLatch在线程上等待。示例:

public class App {
private List<String> workItems;
private AtomicInteger factor = new AtomicInteger(0);
private CountDownLatch countDownLatch = new CountDownLatch(1);

public App() {
workItems = new ArrayList<>();
//create some work in workItmes
workItems.add("apple");
workItems.add("oranges");
workItems.add("bananas");
}

public List<String> getWorkItems() {
return workItems;
}

public CountDownLatch getCountDownLatch() {
return countDownLatch;
}

public void calculateFactor() throws InterruptedException {
TimeUnit.SECONDS.sleep(5);
factor.set(1);
countDownLatch.countDown();
}

public boolean evaluateItem(String item, int factor) {
// do some work based on item and current factor
System.out.println("Received: " + item + " " + factor);
return true;
}

public AtomicInteger getFactor() {
return factor;
}

public static void main(String[] args) throws Exception {
App myApp = new App();
ExecutorService executorService = Executors.newSingleThreadExecutor();

System.out.println("starting...");

executorService.submit(() -> {
try {
myApp.calculateFactor();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("Error when calculating Factor");
}
});
myApp.getCountDownLatch().await();
int currentFactor = myApp.getFactor().get();
List<Boolean> results = myApp.getWorkItems().stream().map(s -> myApp.evaluateItem(s, currentFactor)).collect(toList());
System.out.println(results);


executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.SECONDS);
System.out.println("done");
}
}

输出将是:

starting...
Received: apple 1
Received: oranges 1
Received: bananas 1
[true, true, true]
done

有关 CountDownlLatch 的更多详细信息:https://www.baeldung.com/java-countdown-latch

关于Java:创建一个后台线程来更新变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55489314/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com