从来好事天生俭,自古瓜儿苦后甜。这篇文章主要讲述执行新的runnables时丢失ApplicationContext相关的知识,希望能为你提供帮助。
我知道我是这个春天的新手,但我整天都被困在这里。我不太喜欢提问,但也许我会得到一个想法。
所以这是我的问题:我正在尝试创建一个队列来处理后端的东西。我通过在组件类中创建一个静态执行器服务来实现这一点,并使用辅助方法来运行它们。它似乎像我想要的那样工作,当我在类中连接时,我可以进入这些类,但似乎当它们运行时它们会丢失应用程序上下文(或者这只是我的猜测)。
我确信有更好的方法可以做到这一点,但在我工作的自定义框架中,有许多功能对我不起作用。我没有spring-config.xml,不能使用@Configuration
【执行新的runnables时丢失ApplicationContext】执行者服务组件
@Component
public class FifoComponent {
public static ExecutorService executors = Executors.newSingleThreadExecutor();
private static Lock lock = new ReentrantLock(true);
public static void executeNewTestJob(int i) {
lock.lock();
OrderAllocationTestJob job = new OrderAllocationTestJob(i);
executors.execute(job);
lock.unlock();
}
}
Runnable组件 - 注意appdateutils有一个方法,可以调用一个组件,并在我的典型tomcat环境中正常工作
@Component
public class OrderAllocationTestJob implements Runnable {
int i;
public OrderAllocationTestJob(int i) {
this.i = i;
}@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Asynchronous task " + i);
System.out.println(AppDateUtils.getCurrentTimeStamp());
}
}
从struts 2动作调用(测试)我知道我可以调用appdateutils.gettime方法
for (int i = 0;
i <
50;
i++) {
FifoComponent.executeNewTestJob(i);
}
这是我的最终结果,因为它的价值“范围'请求'对当前线程无效”
Exception in thread "pool-15-thread-50" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dateTimestampDao': Scope 'request' is not active for the current thread;
consider defining a scoped proxy for this bean if you intend to refer to it from a singleton;
nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
答案“我确信有更好的方法可以做到这一点”
基于此,您需要在调用另一个线程之前创建/查找所有请求和会话范围的组件。实际上,请求注入是线程本地的,并且在您的方案中不起作用。
另一答案我想如果你删除
Thread.sleep(100);
在OrderAllocationTestJob中
job.sleep(100);
在FifoComponent中将解决您的问题
另一答案我通过为我的runnables扩展ConcurrentLinkedQueue并将它们保存在我在ServletContextListener的initialize方法中实例化的管理器中解决了这个解决方案。通过重写ConcurrentLinkedQueue的offer()方法来持续轮询直到队列为空,我能够同步处理runnables。
不幸的是,这会锁定请求线程,直到runnable完成,我将不得不让我的用户密切关注它并让我知道页面是否最终运行得很长,但至少在我的测试环境中,这个过程似乎是次秒即使我一次打20个,所以我现在好了。
我仍然更喜欢从我的Tomcat容器执行的ExecutorService,但不在请求的范围内,但除非有人能回答这个问题,否则我现在就要离开
另一答案你看起来像那样吗?
@Component公共类AsynchronousThread扩展Thread {
public static final Logger LOGGER = LoggerFactory
.getLogger(AsynchronousThread.class);
@Autowired
private Writer writer;
private BlockingQueue<
IndexContextDTO>
blockingQueue = new LinkedBlockingQueue<
IndexContextDTO>
(
500);
/**
*
*/
public AsynchronousThread() {
super("AsynchronousThread");
}@PostConstruct
public void init() {
Integer internalQueueSize = 100;
this.blockingQueue = new LinkedBlockingQueue<
>
(internalQueueSize);
this.start();
}@Override
public void run() {while (true) {
// Do stuff
}
}public void putInQueue(IndexContextDTO message) {
try {
this.blockingQueue.put(message);
} catch (InterruptedException interruptedException) {
// This exception will be thrown in very rare case.
LOGGER.error("An error while putting message in the queue. "
+ message, interruptedException);
}
}
}
推荐阅读
- ActionMapper类在struts 2中的作用是什么
- 在Winforms中使用带有C#的InputSimulator以正确的方式模拟按键
- 如何在Symfony 3中为Guzzle创建PSR-6文件系统缓存
- 如何在Atom编辑器中保存时删除结尾的空格
- 使用Symfony2和Doctrine增强数据库处理的5条简单技巧
- 如何在Winforms C#中仅允许数字出现在文本框中
- 如何在Symfony 3中检索信息和任何加密货币(比特币,以太坊)的值
- 如何在Symfony 3中将FWUserBundle与HWIOAuthBundle一起配置和使用(社交登录)
- 如何在C#中从Winforms应用程序打印PDF