考虑下面的一段代码(乍一看似乎不太正常).
static class NumberContainer {
int value = 0;
void increment() {
value++;
}
int getValue() {
return value;
}
}
public static void main(String[] args) {
List<NumberContainer> list = new ArrayList<>();
int numElements = 100000;
for (int i = 0; i < numElements; i++) {
list.add(new NumberContainer());
}
int numIterations = 10000;
for (int j = 0; j < numIterations; j++) {
list.parallelStream().forEach(NumberContainer::increment);
}
list.forEach(container -> {
if (container.getValue() != numIterations) {
System.out.println("Problem!!!");
}
});
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:为了绝对肯定"问题!!!" 将不会打印,NumberContainer类中的"value"变量是否需要标记为volatile? …
我一直在使用Python一段时间来解决实际问题,但我仍然没有对引擎背后发生的事情有一个正确的理论上的理解.例如,我很难理解Python如何将函数视为对象.我知道函数是类'function'的对象,带有'call'方法,我知道我可以通过为它们编写'call方法'来使我的定制类表现得像函数一样.但我无法弄清楚在创建新函数时精确存储在内存中的内容,以及如何访问存储的信息.
为了实验,我写了一个小脚本,它创建了许多函数对象并将它们存储在一个列表中.我注意到这个程序占用了大量内存.
funct_list = []
for i in range(10000000):
def funct(n):
return n + i
funct_list.append(funct)
Run Code Online (Sandbox Code Playgroud)
我的问题是:
在定义新的函数对象时,精确地存储在RAM中的是什么?我是否存储了如何实现该功能的细节?
如果是这样,我的函数对象是否具有允许我"检查"(或甚至可能"追溯"改变"函数行为方式)的属性或方法?
也许我之前的问题是循环的,因为函数对象的方法本身就是函数...
在我上面的代码中,一些RAM仅用于存储列表中我的函数对象的"指针".RAM的其余部分可能用于存储有关我的函数对象实际工作方式的有趣内容.RAM大致如何在这两个目的之间分配?
假设我通过使函数做更复杂的事情来改变代码片段.结果会占用更多的RAM吗?(我希望如此.但是当我通过用1000行垃圾填充其身体来改变我的函数的定义时,所用的RAM量似乎没有任何差别.)
我很想找到关于此的全面参考.但无论我输入谷歌,我似乎无法找到我正在寻找的东西!
我想了解Java fork-join池中处理任务的顺序.
到目前为止,我在文档中找到的唯一相关信息是关于一个名为"asyncMode"的参数,如果此池对从未加入的分叉任务使用本地先进先出调度模式,则为"true" .
我对这个陈述的解释是每个工人都有自己的任务队列; 工人从他们自己的队列前面接受任务,或者如果他们自己的队列是空的,就偷走其他工人队列的后面; 如果asyncMode为true(resp.false),worker会将新分叉的任务添加到自己队列的后面(resp.front).
如果我的解释错误,请纠正我!
现在,这提出了几个问题:
1)加入的分叉任务的顺序是什么?
我的猜测是,当一个任务被分叉时,它会被添加到工作者的队列中,如上面的解释所述.现在,假设任务已加入......
如果在调用join时,任务尚未启动,则工作者调用join将把任务拉出队列并立即开始处理它.
如果在调用join时,该任务已经被另一个worker偷走了,那么调用join的worker将同时处理其他任务(按照我上面的解释中描述的获取任务的顺序),直到它的任务为止.加入已被偷走的工人完成了.
这种猜测基于使用print语句编写简单的测试代码,并观察改变连接调用顺序的方式会影响处理任务的顺序.有人可以告诉我,我的猜测是否正确?
2)外部提交的任务的顺序是什么?
根据此问题的答案,fork-join池不使用外部队列.(顺便说一下,我正在使用Java 8.)
所以我要理解,当外部提交任务时,任务会被添加到随机选择的工作队列中吗?
如果是这样,外部提交的任务是否添加到队列的后面或前面?
最后,这取决于是通过调用pool.execute(任务)还是通过调用pool.invoke(task)来提交任务?这取决于调用pool.execute(task)或pool.invoke(task)的线程是外部线程还是此fork-join池中的线程?
According to Java Concurrency in Practice, it is dangerous to start a thread within a class constructor. The reason is that this exposes the this pointer to another thread before the object is fully constructed.
Despite this topic being discussed in many previous StackOverflow questions, I am still having difficulty understanding why this is such a concern. In particular, I hope to seek clarity on whether starting a thread inside a constructor can lead to memory consistency problems from …