小编Ale*_*der的帖子

线程池并行处理消息,但保留对话中的顺序

我需要并行处理消息,但保留具有相同会话ID的消息的处理顺序.

示例:
让我们像这样定义一条消息:

class Message {
    Message(long id, long conversationId, String someData) {...}
}
Run Code Online (Sandbox Code Playgroud)

假设消息按以下顺序到达:
消息(1,1,"a1"),消息(2,2,"a2"),消息(3,1,"b1"),消息(4,2,"b2) ").

我需要在消息1之后处理消息3,因为消息1和3具有相同的会话ID(类似地,消息4应该在2之后由于相同的原因处理).
我不关心例如1和2之间的相对顺序,因为它们具有不同的会话ID.

我想尽可能多地重用java ThreadPoolExecutor的功能,以避免在我的代码中手动替换死线程等.

更新:可能的'conversation-id'的数量不受限制,并且会话没有时间限制.(我个人认为这不是一个问题,因为我可以从conversationId到工人号码进行简单的映射,例如conversationId%totalWorkers).

更新2:具有多个队列的解决方案存在一个问题,其中队列号由例如' index = Objects.hash(conversationId)%total '确定:如果处理某些消息需要很长时间,则所有消息都包含相同的' index '但不同的' conversationId '将等待,即使其他线程可用来处理它.也就是说,我相信具有单个智能阻塞队列的解决方案会更好,但这只是一个意见,我对任何好的解决方案持开放态度.

你看到这个问题的优雅解决方案吗?

java multithreading

15
推荐指数
2
解决办法
1630
查看次数

Java:手动展开的循环仍比原始循环快。为什么?

考虑下面两个长度为2的代码片段:

boolean isOK(int i) {
    for (int j = 0; j < filters.length; ++j) {
        if (!filters[j].isOK(i)) {
            return false;
        }
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

boolean isOK(int i) {
     return filters[0].isOK(i) && filters[1].isOK(i);
}
Run Code Online (Sandbox Code Playgroud)

我认为,经过充分的预热后,这两块琴的性能应该相似。
我已经使用JMH微基准测试框架(如此此处所述)进行了检查,并观察到第二个片段的运行速度提高了10%以上。

问题:为什么Java没有使用基本循环展开技术优化我的第一个代码段?
特别是,我想了解以下内容:

  1. 我可以很容易地产生一个代码,为2个滤波器的情况下最佳的,仍然可以在过滤器另一个号码的情况下工作(想象一个简单的建造者):
    return (filters.length) == 2 ? new FilterChain2(filters) : new FilterChain1(filters)。JITC可以这样做吗?如果不能,为什么?
  2. JITC是否可以检测到'filters.length == 2 '是最常见的情况,并在预热后产生最适合这种情况的代码?这应该几乎与手动展开的版本一样最佳。
  3. JITC是否可以检测到某个特定实例被非常频繁地使用,然后为该特定实例生成代码(对于该实例,它知道过滤器的数量始终为2)?

理想情况下,我想从对JITC的工作有深刻理解的人那里得到答案。

基准运行细节:

  • 在最新版本的Java 8 OpenJDK和Oracle HotSpot上进行了尝试,结果相似
  • 使用的Java标志:-Xmx4g -Xms4g -server -Xbatch -XX:CICompilerCount = …

java optimization performance jit

10
推荐指数
2
解决办法
347
查看次数

为什么 ZonedDateTime 和 Calendar 对 2050 年的时间不一致?

考虑以下代码:

ZoneId zoneId = ZoneId.of("America/Los_Angeles");
long currMillis = 2530778400000L;
Instant curr = Instant.ofEpochMilli(currMillis);
LocalDateTime dt = LocalDateTime.ofInstant(curr, zoneId); //the local one just for completeness
ZonedDateTime zdt = ZonedDateTime.ofInstant(curr, zoneId);
Calendar calendar = GregorianCalendar.from(zdt);

System.out.println(String.format("%-30s %s", "java-8 LocalDateTime hour:", dt.toLocalTime().getHour()));
System.out.println(String.format("%-30s %s", "java-8 ZonedDateTime hour:", zdt.toLocalTime().getHour()));
System.out.println(String.format("%-30s %s", "Calendar hour:", calendar.get(Calendar.HOUR_OF_DAY)));
Run Code Online (Sandbox Code Playgroud)

打印:

java-8 LocalDateTime hour:     3
java-8 ZonedDateTime hour:     3
Calendar hour:                 2
Run Code Online (Sandbox Code Playgroud)

似乎在这个小时左右,日历从 2 点跳到 4 点(如果对应于 DST 更改,一般来说不一定是问题)。

我正在使用 AdoptOpenJDK 1.8.0_242,但我也检查了 HotSpot 1.8.0_181 - 同样的问题。

为什么日历报告的时间与 ZonedDateTime 不同?
这种不匹配是一个已知问题吗? …

java datetime calendar java-8 zoneddatetime

9
推荐指数
1
解决办法
125
查看次数

几个 java 'activation' 库定义了重叠的类。使用哪一种?

我正在使用相当标准的 Java 库(例如 Spring)的最新稳定版本,但从 maven shade 插件中收到关于定义相同类的三个不同库的“重叠类”警告。

库:jakarta.activation-api, javax.activation-api, activation.

具体来说:

  1. jakarta.activation:jakarta.activation-api:jar:1.2.2(依赖于jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3
  2. javax.activation:javax.activation-api:jar:1.2.0( 的依赖javax.xml.bind:jaxb-api:jar:2.3.1,我认为这个应该换成jakarta.xml.bind-api,但不确定)
  3. javax.activation:activation:jar:1.1(依赖于com.sun.mail:javax.mail:jar:1.6.2

什么图书馆是“正确”的图书馆,会造成最少的麻烦?

更新:似乎jakarta.xml.bind-api替换了javax.xml.bind:jaxb-api(证明:herehere),因此在(1)和(2)之间的冲突中,jakarta one ( jakarta.activation-api) 应该优于 javax one ( javax.activation-api)。Jakarta 网站中描述首选的 JAXB 依赖项。但目前尚不清楚这与javax.activation:activation.

java jaxb maven jakarta-ee

7
推荐指数
1
解决办法
960
查看次数

Maven:确保在多项目开发中使用相同的主要父 pom 版本

我们的团队有多个项目;大多数项目只是库。为简单起见,让我们假设这些库不相互依赖,并且有一个使用它们的项目,例如:

Project Main:
    Project Lib-A:
        X (3rd-party library)
    Project Lib-B:
        X (3rd-party library)
Run Code Online (Sandbox Code Playgroud)

为了避免在“Main”中出现意外,我们希望确保我们自己的所有项目都使用相同版本的第 3 方库,以便例如构建“Lib-A”和“Lib-B”使用相同版本的库 X 进行测试。

为了实现这一点,我们使用了一个父 pom,其中包含<dependencyManagement>详细说明所有相关 3rd-party 库的版本及其传递依赖项的部分。这个父 pom 被所有项目继承,即上面示例中的“Main”、“Lib-A”和“Lib-B”。然后每个子 pom 只会使用<dependency>而不指定任何版本。我们还有Maven 执行器插件的依赖收敛规则,以确保我们没有错过任何项目中的任何库冲突。

问题:增加 X 的版本:'Lib-A' 的开发者将 X 的版本从 1.0 增加到 2.0。因此,他更改了父 pom 中 X 的版本,增加了父 pom 的版本,释放了父 pom,并通知来自“Main”的人他们现在应该使用新的父 pom。情况变成这样:

Main - inherits from Parent:2.0 and depends on:
    Lib-A:2.0 - inherits from Parent 2.0 and depends on X:2.0
    Lib-B:1.0 - inherits from Parent 1.0 and depends on …
Run Code Online (Sandbox Code Playgroud)

maven maven-enforcer-plugin maven-dependency

6
推荐指数
1
解决办法
204
查看次数

MyBatis:如何绕过本地缓存并在特定选择上直接命中数据库

我使用MyBatis 3.1.
当我需要绕过MyBatis本地缓存并直接命中数据库时,我有两个用例.
由于MyBatis配置文件只有全局设置,因此不适用于我的情况,因为我需要它作为例外,而不是默认情况.MyBatis <select> XML语句的属性似乎不包含此选项.

用例1:'从双重选择sysdate'.
MyBatis缓存导致此缓存始终在MyBatis会话中返回相同的值.当我尝试复制过时条目的情况时,这会导致我的集成测试出现问题.
我的解决方法是使用普通的JDBC调用.

用例2:从一个线程中"选择"并不总是看到另一个线程写入的值.
线程1:

SomeObject stored = dao.insertSomeObject(obj);
runInAnotherThread(stored.getId());
//complete and commit
Run Code Online (Sandbox Code Playgroud)

线程2:

//'id' received as an argument provided to 'runInAnotherThread(...)'
SomeObject stored = dao.findById(id);
int count = 0;
while(stored == null && count < 300) {
    ++count;
    Thread.sleep(1000);
    stored = dao.findById(id);
}
if (stored == null) {
    throw new MyException("There is no SomeObject with id="+id);
}
Run Code Online (Sandbox Code Playgroud)

我偶尔会在服务器上收到MyException错误,但无法在我的本地计算机上重现.在所有情况下,对象始终在DB中.所以我猜错误取决于第一次存储的对象是否在MyBatis本地缓存中,等待5分钟没有帮助,因为它从不检查实际的数据库.

所以我的问题是如何在不退回普通JDBC的情况下解决MyBatis中的上述用例?
能够以某种方式告知MyBatis不在特定调用中使用缓存值(最好)或在特定查询的所有调用中将是首选选项,但我也会考虑任何解决方法.

java spring mybatis

5
推荐指数
3
解决办法
1万
查看次数

如何在Apache Spark中实现任务的动态负载平衡

我知道在Spark中我可以通过使用多个分区来分割我的计算.如果说我可以将输入RDD拆分为1000个分区并且我的机器数量为100,那么Spark会将计算分成1000个任务,并以某种智能方式将它们动态分配到我的100台机器中.

现在假设我最初可以将数据拆分为仅2个分区,但我仍然有100台机器.当然,我的98台机器将闲置.但是当我处理每个任务时,我可能会将其拆分为可能在不同机器上执行的子任务.它可以在带有队列的普通Java中轻松实现,但我不确定在Apache Spark中攻击它的最佳方法是什么.

考虑以下Java伪代码:

BlockingQueue<Task> q = new LinkedBlockingQueue<Task>();
q.push(myInitialTask);
...
//On each thread:
while (!queue.isEmpty()) {
    Task nextTask = queue.take();
    List<Task> newTasks = process_task_and_split_to_sub_tasks(nextTask);
    queue.pushAll(newTasks);
} 
Run Code Online (Sandbox Code Playgroud)

假设方法' process_task_and_split_to_sub_tasks() '可以将任何大型任务拆分为多个较小的任务,上述Java代码将使我的所有100个线程保持忙碌.

有没有办法在Spark中实现相同的功能,可能与其他工具结合使用?


更新:已经正确地指出,攻击它的方法之一就是

  1. 生成更精细的密钥和
  2. 然后使用智能分区程序将这些密钥分配给分区.

我想这是解决这个问题的"经典"方法,但它要求我能够正确估计每个键的工作量以正确分区.如果我没有提前知道每个密钥的工作量怎么办?当我的大部分机器都闲置等待一些不幸的机器时,我可能最终会遇到非常不幸的分区.

示例:我们以简化的频繁项集挖掘为例.
假设我的文件包含带有字母a到j(10个字母)的行,每行中的所有字母都按字母顺序排序而不重复,例如'abcf',任务是找到所有行中50%存在的所有字母组合.例如,如果许多行匹配模式'ab.*f',那么输出将包含{'a','b','f','ab','af','bf','abf'}.
实现它的方法之一是将所有以'a'开头的行发送到一个映射器(机器),所有行以'b'开头到另一个映射器.顺便说一下,这是在Spark中实现频繁模式挖掘的方式.现在假设我有100台机器(但只有10个字母).然后我的90台机器将闲置.
使用更精细的密钥解决方案,我可以生成10,000个4个字母的前缀,然后根据每个前缀的估计工作以某种方式对它们进行分区.但是我的分区可能非常错误:如果大多数行以'abcd'开头,那么所有的工作都将由负责此前缀的机器完成(除了它之外可能还有其他前缀),再次产生一个当我的大多数机器闲置等待一些不幸的机器时的情况.

在这种情况下,动态负载平衡将是这样的:接收到以"a"开头的行的映射器可能希望进一步分割其行 - 以'ab','ac','ad'开头, ...然后将它们发送给其他10台机器,这些机器可能会决定将其工作进一步分解为更多任务.
我知道标准的Apache Spark没有开箱即用的答案,但我想知道是否有办法实现这一目标.

Kafka(即上面的队列)+ Spark Streaming看起来很有前途,您认为我能够以相对简单的方式使用这些工具来实现动态负载平衡吗?你能推荐其他工具吗?

load-balancing job-scheduling apache-spark spark-streaming

5
推荐指数
1
解决办法
1431
查看次数

Go/Cgo:生成没有 Go 运行时函数定义的静态库

有没有办法从 Go 代码生成 C 静态库,但没有 Go 运行时函数定义

理由

  • Project Ago build -buildmode=c-archive使用,创建一个 C 静态库libA.a
  • 效果很好:project B使用纯 C 语言,能够轻松创建可执行文件,静态链接libA.a,一切都很好。
  • 问题1:project C碰巧也使用Go,但想用作libA.a 常规C库。现在它有一个链接问题:Go 运行时函数(例如eg)_cgo_panic现在在project C运行时(因为它使用Go)和libA.a.
  • 问题2:project D使用纯C,与B相同。但它想使用两个不同的库project A,例如libA.a和一些libA2.a。遗憾的是,它也没有链接,因为 Go 运行时函数现在都在 和 中libA.a定义libA2.a

如果可以生成不包含 Go 运行时定义的库,project C则 和所面临的问题project D可以轻松解决。可以直接链接到. 会链接到,有些会包含所有 Go 运行时内容的定义。project AProject C …

c linker static-libraries go cgo

5
推荐指数
1
解决办法
1127
查看次数

是否可以结合MyBatis和QueryDSL/jOOQ?

MyBatis提供了映射,本地缓存和开箱即用的日志记录.
因此,QueryDSL/jOOQ提供SQL语句的编译时检查和IDE自动完成.
是否可以将它们结合起来?

换句话说,我想用QueryDSL或jOOQ创建一个查询,然后使用MyBatis的一些粘合代码/适配器执行它.

我已经检查过:

  • 我考虑使用QueryDSL生成SQL查询字符串,并在MyBatis中使用它们的'@SelectProvider'注释,但它似乎是一个死胡同:MyBatis在其SQL字符串中需要"$ {xxx}",但QueryDSL只生成查询基于实际的Java类型,因此即使对于ID也不起作用.
  • MyBatis Generator作为QueryDSL/jOOQ的替代品:非常差的替代方案,因为它实际上生成了一个样板代码,您稍后将需要维护和扩展
  • MyBatis SQL Builder作为QueryDSL/jOOQ的替代品:比QueryDSL或jOOQ弱得多,例如它不提供列名的编译时检查,它更麻烦,它依赖于'@SelectProvider',它使代码复杂化

java querydsl mybatis jooq spring-data

4
推荐指数
1
解决办法
3725
查看次数

在RESTful URL中使用动词和形容词的替代方法

我想在我的REST API中添加操作,以便在不同的"商店"之间移动"资源".

例如,假设我的资源通常由以下URL访问:

/resources
/resources/{resourceId}
Run Code Online (Sandbox Code Playgroud)

现在假设我想'停用'某些资源,即从概念上将其移动到另一个子文件夹.允许这种情况的最直接的方法如下.

  1. '停用'资源,即使其在/ resources下不可用.从概念上讲,它将对象'移动'到' / resources/deactivated / '子文件夹:

    POST /resources/{resourceId}/deactivate   
    
    Run Code Online (Sandbox Code Playgroud)

    或者:

    POST /resources/deactivated/{resourceId}
    
    Run Code Online (Sandbox Code Playgroud)
  2. 获取所有已停用的对象:

    GET /resources/deactivated      
    
    Run Code Online (Sandbox Code Playgroud)
  3. 反转'deactivate'动作,即概念上将对象从' / resources/deactivated / '子文件夹移回主要文件夹(' / resources ').

    POST /resources/{resourceId}/reactivate    
    
    Run Code Online (Sandbox Code Playgroud)

    要么

    POST /resources/deactivated/{resourceId}/restore     
    
    Run Code Online (Sandbox Code Playgroud)

    这个API对我来说似乎很直观.但它似乎违反了我在许多最佳实践中看到的"首选名词"规则 - 关于REST API的文章:我使用动词和形容词而不是名词!

请注意,我可能有所有端点的参数,例如GET/resources/deactivated?createdBefore = 01022017

我的REST API有更好的替代方案吗?即更多RESTful,但不是更直观的?

我能找到关于这个主题的好资源:

api rest restful-url

1
推荐指数
1
解决办法
2226
查看次数