Tag: 弹簧

等待所有线程在Spring Integration中完成

我有一个自我执行的jar程序,它很大程度上依赖于Spring Integration。 我遇到的问题是程序在其他Spring bean完成之前终止 。 下面是我正在使用的代码的简化版本,如果需要,我可以提供更多代码/配置。 入口点是一个main()方法,它引导Spring并启动导入过程: public static void main(String[] args) { ctx = new ClassPathXmlApplicationContext(“flow.xml”); DataImporter importer = (DataImporter)ctx.getBean(“MyImporterBean”); try { importer.startImport(); } catch (Exception e) { e.printStackTrace(); } finally { ctx.close(); } } DataImporter包含一个简单的循环,可以将消息发送到Spring Integration网关。 这为流提供了一种主动的“推送”方法,而不是轮询数据的常用方法。 这是我的问题所在: public void startImport() throws Exception { for (Item item : items) { gatewayBean.publish(item); Thread.sleep(200); // […]

Spring Batch Multi Threading – 如何让每个线程读取唯一记录?

许多论坛已经多次询问过这个问题。 但我没有看到适合我的答案。 我试图在我的春季批处理实现中实现multithreading步骤。 有一个包含100k记录的临时表 想要在每个线程的10个提交间隔300个线程中处理它 – 所以在任何时间点都有3000个记录。 我定义了一个任务执行器,并在我想要multithreading的步骤中引用它 我的想法是,首先我将获得线程池大小(10)并使用velue(可以是1-10)更新thread_id列到每个100k记录。 在这种情况下,有10个线程和100k记录,因此10k记录将被分配一个id – 我正在尝试实现一个stagingsteplistener来执行此操作。 为这个临时表写了一个读者。 任务执行器将创建10个读者,每个读者必须读取300个不同的记录并处理它们 – 现在我如何在步骤监听器和读取器之间传递一个公共ID,以便每个线程都有自己的一组记录来处理。 截至目前,我只有一个JVM。 所以我想在Multi Threaded步骤中做这个,而不是考虑基于分区的方法。 请帮忙…… 我提到了pro spring批处理书并创建了一个临时步骤监听器,它使用作业参数从作业配置xml接受运行ID,如下所示 我找不到的是这个? 这个“run.id”来自哪里。 我在书中的任何地方都没有看到。 我在我的spring批处理中复制了相同的实现,当我运行它时,我看到exception说run.id是不可识别的。 请帮我讲一下如何做到这一点?

如何自动assemblySpring TaskExecutor创建的线程?

根据Spring的文档 ,使用TaskExecutor的方法如下: import org.springframework.core.task.TaskExecutor; public class TaskExecutorExample { private class MessagePrinterTask implements Runnable { private String message; public MessagePrinterTask(String message) { this.message = message; } public void run() { System.out.println(message); } } private TaskExecutor taskExecutor; public TaskExecutorExample(TaskExecutor taskExecutor) { this.taskExecutor = taskExecutor; } public void printMessages() { for(int i = 0; i < 25; i++) […]

使用Spring设计Java库

我正在从现有程序中将一些function提取到一个单独的库中。 这个程序使用Spring进行dependency injection和其他任务,我也想继续在库中使用它。 这个库需要监视文件系统的更改,因此它将启动某种单独的线程来执行此操作。 我真的不知道我对库的初始化有什么选择: 如何初始化库的上下文? 我不能假设库用户也会使用Spring,但我可以使用库分发Spring。 如何管理文件系统监控线程? 期望程序实例化库的主类和调用init或类似的东西是好的设计吗?

@Async阻止线程继续,直到其他线程完成

我有一个应用程序,其中需要计算一定数量的东西。 此计算函数具有注释@Async(来自Spring Framework),这使得可以在4个线程上运行这些计算。 问题是我需要大约40000个这样的计算,我想知道所有计算的开始和结束之间的时间,所以我看看在调用计算函数的for循环之前和之后的时间。 但是现在所有的计算都被放入队列中,因此for循环立即结束,时间就像1秒钟,而计算完成需要几个小时。 我已经尝试将最大队列大小设置为大约100(也很好地减少了内存使用量),但这也没有解决方案,因为我将错过它花费的总时间中的最后100次计算。 有没有办法在for循环之后暂停执行代码,直到所有线程完成其工作,但仍然能够使用@Async注释? 这是一些说明相同问题的代码: 执行课程: public class Foo { public void executeBlaALotOfTimes() { long before = System.currentTimeMillis(); for (int i = 0; i<40000; i++) { executeBla(); } long after = System.currentTimeMillis(); System.out.println("Time it took for a lot of bla to execute: " + (after – before) / 1000.0 + " seconds."); […]

使用Spring / EHCache加载时刷新缓存

我在SpringmultithreadingWeb服务上有一个缓存问题,它带有数据库后端和基于EHCache的缓存。 该服务有许多客户端一次又一次地请求相同的对象,每秒有几十个请求。 经常请求的对象只有几个,并且不经常请求大量其他对象。 对象每隔几分钟就可以更改一次,因此缓存的TTL设置为一分钟。 从数据库加载对象很慢,至少需要几秒钟。 起初我使用了一个天真的实现来获取对象: 检查对象是否在缓存中。 如果是,请从缓存中返回。 如果没有,从数据库加载它,将其放入缓存并返回它。 这在最初在本地测试时运行良好。 但是,每当一个更频繁请求的对象在缓存中到期时,在更快的服务器上进行性能测试就会显示一些非常糟糕的负载峰值。 发生这种情况时,在接下来的10秒内,对该对象的所有请求都将导致数据库加载,直到第一个线程完成数据库加载并将新对象放入缓存。 结果是数据库上的负载很短但非常高,并且许多用户需要等待请求完成。 我当前的实现通过跟踪当前正在加载哪个对象来改进数据库负载: 检查对象是否被缓存。 如果是,请从缓存中返回。 如果没有,请检查当前是否正在加载对象。 如果是,请等待另一个线程的加载完成,从缓存中获取新对象并返回它。 如果不是,则将对象放入加载对象列表中,完成后将其放入缓存中并返回。 通过此实现,即使对象到期,也只有一个数据库操作。 而且,由于数据库负载较低,它也会更快完成。 但它仍然意味着在对象加载期间请求对象的所有用户都需要等待。 我真正想要的是只有第一个线程等待数据库加载,而所有其他线程只是在加载对象时返回’过期’对象。 对于我来说,响应时间比对象太老了几秒钟更重要。 或者,当我注意到对象将在几秒钟内过期时,我可以异步刷新缓存。 这更接近EHCache的单个TTL模型,并且意味着没有人需要等待数据库负载 我真正的问题是:在我重新发明轮子之前,是否有任何现有的框架已经实现了这样的东西(在Spring / EHCache环境中)? 或者也许在Spring / EHCache的某处已经存在对此的支持,我找不到合适的选项?

Spring AOP使用Java 8提供IllegalArgumentException

使用Java 8和Spring AOP 4.0.6我收到以下错误 java.lang.RuntimeException: Error scanning file MonitorAroundPerformance.class at org.eclipse.jetty.annotations.AnnotationParser.parseDir(AnnotationParser.java:705) at org.eclipse.jetty.annotations.AnnotationParser.parseDir(AnnotationParser.java:686) at org.eclipse.jetty.annotations.AnnotationParser.parseDir(AnnotationParser.java:686) at org.eclipse.jetty.annotations.AnnotationParser.parseDir(AnnotationParser.java:686) at org.eclipse.jetty.annotations.AnnotationParser.parseDir(AnnotationParser.java:686) at org.eclipse.jetty.annotations.AnnotationParser.parseDir(AnnotationParser.java:686) at org.eclipse.jetty.annotations.AnnotationParser.parse(AnnotationParser.java:821) at org.eclipse.jetty.annotations.AnnotationConfiguration$ParserTask.call(AnnotationConfiguration.java:159) at org.eclipse.jetty.annotations.AnnotationConfiguration$1.run(AnnotationConfiguration.java:531) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:607) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:536) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.IllegalArgumentException at org.objectweb.asm.ClassReader.(Unknown Source) at org.objectweb.asm.ClassReader.(Unknown Source) at org.objectweb.asm.ClassReader.(Unknown Source) at org.eclipse.jetty.annotations.AnnotationParser.scanClass(AnnotationParser.java:970) at org.eclipse.jetty.annotations.AnnotationParser.parseDir(AnnotationParser.java:700) at org.eclipse.jetty.annotations.AnnotationParser.parseDir(AnnotationParser.java:686) at org.eclipse.jetty.annotations.AnnotationParser.parseDir(AnnotationParser.java:686) at org.eclipse.jetty.annotations.AnnotationParser.parseDir(AnnotationParser.java:686) […]

会话范围bean作为Spring MVC Controller的类属性

我有一个User类: @Component @Scope(“session”) public class User { private String username; } 还有一个Controller类: @Controller public class UserManager { @Autowired private User user; @ModelAttribute(“user”) private User createUser() { return user; } @RequestMapping(value = “/user”) public String getUser(HttpServletRequest request) { Random r = new Random(); user.setUsername(new Double(r.nextDouble()).toString()); request.getSession().invalidate(); request.getSession(true); return “user”; } } 我使会话无效,以便下次到达/ users时,我会得到另一个用户。 由于用户的会话范围,我期待不同的用户,但我得到了相同的用户。 我检查了调试模式,它在内存中是相同的对象ID。 我的bean被声明为: […]

如何将Spring事务传播到另一个线程?

也许,我做错了什么,但我找不到适合下列情况的好方法。 我想对使用下面的Spring Batch执行作业的服务进行unit testing。 作业通过预先配置的AsyncTaskExecutor在单独的线程中执行。 在我的unit testing中,我想: 创建几个域对象并通过DAO保留它们 调用服务方法以启动作业 等到作业完成 使用DAO检索域对象并检查其状态 显然,以上所有内容都应该在一个事务中执行,但不幸的是, 事务不会传播到新线程 (我理解这背后的基本原理)。 我想到的想法: 在步骤(1)之后提交事务#1。 不好,因为在unit testing后应该回滚DB状态。 在作业配置中使用Isolation.READ_UNCOMMITTED 。 但这需要两种不同的配置用于测试和生产。

春季交易管理测试

我想使用SpringContextTests测试我的Dao类。 在我的方法类中,我扩展了AbstractTransactionalJUnit4SpringContextTests ,以便我的测试类与JUnit4集成。 我还设置了配置,并在@After中的@Before和tearDown中清理初始化和数据库。 我的测试类很完美。 我的问题是,当我运行我的测试类并且数据库充满了数据时,原始数据没有回滚,我的数据库被清除。 在@Before方法中,我清除数据库并填充数据,认为我将能够回滚它,但事实并非如此。 任何人都可以找到一个可以在数据库中工作和回滚信息的示例。 ADDONS: 我的测试方法中的每个数据库操作都会被回滚。 但是在@Before方法中执行super.deleteFromTables(“person”)并没有回滚数据库中的所有先前数据。 Spring回滚所有CRUD操作,但在事务不回滚之前清理数据库。