是否存在线程池(在Java中)的任何实现,以确保在同一线程上执行相同逻辑ID的所有任务?
我所追求的逻辑是,如果在给定逻辑ID的特定线程上已经执行了任务,则在同一线程上安排具有相同ID的新任务.如果没有线程为同一ID执行任务,则可以使用任何线程.
这将允许并行执行不相关ID的任务,但是同一ID的任务将以串行和提交的顺序执行.
如果没有,是否有任何关于如何扩展ThreadPoolExecutor以获得此行为的建议(如果可能的话)?
UPDATE
花了更长时间考虑这个问题,我实际上并不要求在同一个线程上执行相同逻辑ID的任务,只是它们不会同时执行.
这方面的一个例子是处理客户订单的系统,可以同时处理多个订单,但不能同一个客户(并且必须按顺序处理同一客户的所有订单).
我现在采用的方法是使用标准的ThreadPoolExecutor,自定义BlockingQueue并Runnable使用自定义包装器进行包装.的Runnable包装器逻辑是:
ConcurrentHashMap)以查看当前是否正在运行相同ID的任务
然后,队列的poll()方法只返回具有当前不在"运行"集中的ID的任务.
这样做的问题在于,我确信会有很多我没有想过的极端情况,因此需要进行大量的测试.
我正在尝试找到一种方法,可以在同一组项目中使用多个版本的Visual Studio.我们的大多数团队使用2008年,但我正在尝试2010年.所有项目都是C#.
据我了解,Visual Studio 2010坚持升级所有项目,因此不可能将所有解决方案/项目文件保留为2008版本.我真的不想分支整个源代码树,所以我想找到一种方法让多个版本的项目文件共存.目前,我已经复制了所有.sln和.csproj文件,所以我有:
# 2008 versions
SolutionName.sln
ProjectA.csproj
ProjectB.csproj
# 2010 versions
SolutionName.vs2010.sln
ProjectA.vs2010.csproj
ProjectB.vs2010.csproj
Run Code Online (Sandbox Code Playgroud)
麻烦的是,尽管2010版本的文件都具有与2008年版本相同的程序集名称,但Visual Studio(2010)认为这些项目都是如此ProjectName.vs2010.在VS中重命名项目失败,并显示一条消息,指出已存在同名文件.
我不认为将2010版本放在子文件夹中会是一个解决方案,因为它会搞砸文件中的任何相对路径.
所以:
UPDATE
我最初声称Visual Studio无法找到项目引用是错误的,因为它使用的是文件名.我遇到的具体问题是,在我的构建文件中,项目引用的形式如下:
<ProjectReference Include="..\..\path\to\ProjectName.vs2010.csproj">
<Project>{48354450-2462-449D-8B32-EFECA39F6CD7}</Project>
<Name>ProjectName</Name>
</ProjectReference>
Run Code Online (Sandbox Code Playgroud)
我复制的项目文件显然有不同的ID(或<Project>元素中的任何内容.只需从构建文件中删除元素就可以解决该特定问题:
<ProjectReference Include="..\..\path\to\ProjectName.vs2010.csproj">
<Name>ProjectName</Name>
</ProjectReference>
Run Code Online (Sandbox Code Playgroud)
话虽如此,复制项目和解决方案文件的整个过程实际上是比它的价值更多的努力,所以我不推荐这种方法.
是否有CLR编译器/ JIT执行的转义分析?例如,在Java中,似乎循环变量是在循环中分配的不会转义循环的对象在堆栈而不是堆上分配(请参阅Java中的Escape分析).
为了澄清,在下面的示例中,编译器会优化掉堆分配,foo因为它永远不会从循环中逃脱.
class Foo
{
int number;
Foo(int number) { this.number = number; }
public override string ToString() { return number.ToString(); }
}
for (int i = 0; i < 10000000; i++)
{
Foo foo = new Foo(i);
Console.WriteLine(foo.ToString());
}
Run Code Online (Sandbox Code Playgroud) 我们有一个应用程序可以在几个Dictionarys 中保存大量对象,其中一些在应用程序的生命周期中不断增长(交易应用程序包含大量工具和不断增长的订单/交易).
OutOfMemoryException由于大对象堆的碎片,我们遇到了问题.
为了解决这个问题,我试图写一个"大"字典,它实现为一个两级字典,其中所有的叶子字典都不够大,不能在LOH上分配.我使用了一致的哈希算法,以避免在单个存储桶变得太大时重新整理整个字典.一致的哈希'circle' TreeDictionary来自C5集合库.
我的问题是,C#有没有更好的数据结构(或者我描述的更好的实现)?
更新
这是"大型"字典的实现:https://gist.github.com/956621
我知道它不是万无一失的,因为LOH堆阈值既不在规范中,也不是每个Dictionary条目或缩放算法的大小.然而,这是目前我能想到的最好的,以避免应用程序在中午爆炸.
我有一个循环变量似乎没有收集垃圾(根据Red-Gate ANTS内存分析器),尽管已超出范围.
代码看起来像这样:
while (true)
{
var item = blockingQueue.dequeue(); // blocks until an item is added to blockingQueue
// do something with item
}
Run Code Online (Sandbox Code Playgroud)
据我所知,在返回item之前提到遗骸blockingQueue.dequeue().这是预期的行为,还是内存分析器中的错误?
其次,如果这是预期的行为,我将如何强制item在循环体的末端收集?将其设置为null似乎不会导致它被收集.这很重要,因为队列可能会长时间阻塞并item引用相当大的对象树.
请注意,探查器的文档说在执行内存快照之前执行了GC,并且引用不在终结器队列上.
我能够在这里用代码重现同样的问题.
更新
要点中的代码略有缺陷,因为它合法地保留了参考文献GetFoo().已经改变了它的对象也时明确设置为现在得到收集null.但是,我相信汉斯的回答解释了我在实际代码中看到的情况.
我目前正在寻找一个写时复制集实现,并希望确认它的线程安全.我很确定它可能不是唯一的方法是允许编译器在某些方法中重新排序语句.例如,该Remove方法如下所示:
public bool Remove(T item)
{
var newHashSet = new HashSet<T>(hashSet);
var removed = newHashSet.Remove(item);
hashSet = newHashSet;
return removed;
}
Run Code Online (Sandbox Code Playgroud)
其中hashSet定义为
private volatile HashSet<T> hashSet;
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,假设hashSet是volatile,它意味着Remove新集合在写入成员变量之前发生了吗?如果没有,那么其他线程可能会在删除发生之前看到该集合.
我实际上没有在生产中看到任何问题,但我只是想确认它是安全的.
UPDATE
更具体地说,还有另一种获得方法IEnumerator:
public IEnumerator<T> GetEnumerator()
{
return hashSet.GetEnumerator();
}
Run Code Online (Sandbox Code Playgroud)
所以更具体的问题是:是否保证返回的IEnumerator永远不会ConcurrentModificationException从删除中抛出?
更新2
对不起,答案都是针对多个作者的线程安全问题.提出了好点,但这不是我想在这里找到的.我想知道是否允许编译器将操作重新排序为Remove以下内容:
var newHashSet = new HashSet<T>(hashSet);
hashSet = newHashSet; // swapped
var removed = newHashSet.Remove(item); // swapped
return removed;
Run Code Online (Sandbox Code Playgroud)
如果这是可能的,那么这意味着线程可以GetEnumerator在hashSet分配之后调用,但在item删除之前,这可能导致在枚举期间修改集合. …
我是从Java背景来到C#并且继续遇到与Java中解决的泛型相同的问题.
鉴于课程:
interface IUntypedField { }
class Field<TValue> : IUntypedField { }
interface IFieldMap
{
void Put<TValue>(Field<TValue> field, TValue value);
TValue Get<TValue>(Field<TValue> field);
}
Run Code Online (Sandbox Code Playgroud)
我想写一些类似的东西:
class MapCopier
{
void Copy(IEnumerable<IUntypedField> fields, IFieldMap from, IFieldMap to)
{
foreach (var field in fields)
Copy(field, from, to); // <-- clearly doesn't compile as field is IUntypedField not Field
}
void Copy<TValue>(Field<TValue> field, IFieldMap from, IFieldMap to)
{
to.Put(field, from.Get(field));
}
}
Run Code Online (Sandbox Code Playgroud)
在Java中,这很容易解决,因为字段集合将是一个Iterable<Field<?>>,你可以Copy(Field, IFieldMap, IFieldMap)直接调用.
在C#中,我发现自己正在为所有可能的值进行切换/转换TValue(可怕的气味,必须为您添加的每种类型添加一个案例显然是等待发生的错误,并且只有在类型集合有限时才可行):
foreach (var …Run Code Online (Sandbox Code Playgroud) 我有这个代码,我想捕获字母异常,但它一直有这些错误:
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:840)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.nextInt(Scanner.java:2091)
at java.util.Scanner.nextInt(Scanner.java:2050)
at exercise_one.Exercise.main(Exercise.java:17)
Run Code Online (Sandbox Code Playgroud)
这是我的代码:
System.out.print("Enter the number of students: ");
students = input.nextInt();
while (students <= 0) {
try {
System.out.print("Enter the number of students: ");
students = input.nextInt();
}
catch (InputMismatchException e) {
System.out.print("Enter the number of students");
}
}
Run Code Online (Sandbox Code Playgroud) 我有一个DataTable从远程JSON填充的DataSource:
var dataSource = new Y.DataSource.Get({ source: url });
dataSource.plug(Y.Plugin.DataSourceJSONSchema, {
schema: {
resultListLocator: "results",
resultFields: [ "field1", "field2" ]
}
});
var table = new Y.DataTable({ columns = ["col1", "col2"] }
table.plug(Y.Plugin.DataTableDataSource, { datasource: dataSource });
table.render("#table");
table.datasource.load({ request: query });
Run Code Online (Sandbox Code Playgroud)
我试图让表中的数据定期刷新. 一个论坛海报建议定期调用负载,我已经尝试过并且它正如我希望的那样工作(数据刷新而不显示正在加载...消息).
Y.later(1000/*ms*/, table.datasource, table.datasource.load, { request: query }, true);
Run Code Online (Sandbox Code Playgroud)
但是,我注意到Chrome中存在内存泄漏.表单元格似乎没有从内存中删除.Chrome的堆分析器报告了很多HTMLTableCellElement对象Detached DOM tree.
这是刷新数据的最佳方法吗?如果是这样,有没有办法清除旧的表格单元格?
备择方案
还有一个datatable-polling模块可以定期获取数据.我不能说任何关于如何与YUI3一起使用的例子DataTable.但是,来自YUI2的示例显示您可以执行以下操作,这似乎有效:
dataSource.setInterval(1000,
{
request: query,
callback:
{ …Run Code Online (Sandbox Code Playgroud) 为什么以下代码使用引用自身的循环const变量进行编译?
#include <iostream>
extern int main(int argc, char* argv[])
{
const int foo = foo * 60;
std::cout << foo << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我正在使用SUNWspro编译器在Solaris 5.10 x86主机上进行编译:
/opt/SUNWspro/bin/CC test.cpp
Run Code Online (Sandbox Code Playgroud)
为了完整性,这是它打印的内容:
$ ./a.out
-519270512
Run Code Online (Sandbox Code Playgroud) c# ×6
java ×2
c++ ×1
clr ×1
const ×1
dom ×1
generics ×1
javascript ×1
jit ×1
lock-free ×1
loops ×1
mismatch ×1
optimization ×1
scope ×1
threadpool ×1
try-catch ×1
volatile ×1
while-loop ×1
yui ×1
yui3 ×1