我已经使用Spring Framework' Scheduled
来安排我的工作每隔5分钟使用cron运行一次。但是有时候我的工作无限期地等待外部资源,我不能在那里暂停。我无法使用fixedDelay
作为先前的进程,有时会进入等待无限模式,我必须每隔5分钟刷新数据。
所以我在Spring框架Scheduled
中寻找任何选项,以便在fixed-time
成功运行之后停止该进程/线程。
我在下面的设置中找到ThreadPoolExecutor
初始化keepAliveTime
,@Configuration
为@Bean(destroyMethod="shutdown")
public Executor taskExecutor() {
int coreThreads = 8;
int maxThreads = 20;
final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
coreThreads, maxThreads, 120L,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()
);
threadPoolExecutor.allowCoreThreadTimeOut(true);
return threadPoolExecutor;
}
我放入LogManager.LogFactory = new Log4NetFactory(configureLog4Net: true);
课程。任何人都能告诉我这项工作是否符合我的预期。
{{1}}
答案 0 :(得分:8)
我不确定这会按预期工作。确实keepAlive用于IDLE线程,我不知道你的等待资源的线程是否处于IDLE状态。此外,只有当线程数大于核心时,才能真正知道它何时发生,除非你监视线程池。
keepAliveTime - 当线程数大于核心时,这是多余空闲线程在终止之前等待新任务的最长时间。
您可以做的是:
public class MyTask {
private final long timeout;
public MyTask(long timeout) {
this.timeout = timeout;
}
@Scheduled(cron = "")
public void cronTask() {
Future<Object> result = doSomething();
result.get(timeout, TimeUnit.MILLISECONDS);
}
@Async
Future<Object> doSomething() {
//what i should do
//get ressources etc...
}
}
不要忘记添加@EnableAsync
通过实施Callable,在没有@Async
的情况下也可以这样做。
编辑:请记住,它会等到超时,但运行任务的线程不会被中断。发生TimeoutException时,您需要调用Future.cancel。并在任务中检查isInterrupted()以停止处理。如果你正在调用api,请确保选中了isInterrupted()。
答案 1 :(得分:7)
allowCoreThreadTimeOut 和 timeout 设置无效,导致它只允许工作线程在一段时间后无法工作(参见javadocs)
你说你的工作无限期地等待外部资源。我确定这是因为您(或您使用的某些第三方库)使用的套接字默认超时。 还要记住jvm在socket.connect / read上阻塞时忽略了Thread.interrupt()。
因此找出你的任务中使用的女巫套接字库(以及它是如何使用的)并更改它的默认超时设置。
例如:在Spring内部广泛使用 RestTemplate (在休息客户端,春季社交,春季安全OAuth等)。并且有ClientHttpRequestFactory实现来创建RestTemplate实例。默认情况下,spring使用SimpleClientHttpRequestFactory使用JDK套接字。默认情况下,所有超时都是无限的。
因此,找出你准确冻结的位置,阅读它的文档并正确配置它。
P.S。如果您没有足够的时间并且“感到幸运”,请尝试使用设置jvm属性 sun.net.client.defaultConnectTimeout 来运行您的应用程序, sun.net.client.defaultReadTimeout 到一些合理的值(详见docs)
答案 2 :(得分:2)
QBluetoothLocalDevice localDevice;
QString localDeviceName;
// Check if Bluetooth is available on this device
if (localDevice.isValid()) {
// Turn Bluetooth on
localDevice.powerOn();
// Read local device name
localDeviceName = localDevice.name();
// Make it visible to others
localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable);
// Get connected devices
QList<QBluetoothAddress> remotes;
remotes = localDevice.connectedDevices();
ui->textBrowser->setText(localDevice.name() + "\n" + localDevice.address().toString());
}
仅用于清除一段时间内不需要的工作线程 - 它对提交给执行程序的任务的执行时间没有任何影响。
如果花时间考虑中断,你可以启动一个新线程并加入超时,如果没有及时完成则中断它。
keepAliveTime