假设我有两个线程像这样运行:
线程A执行工作速度很快,比如每秒100万更新,所以我怀疑经常锁定/互斥锁/监视器是个坏主意。但是如果没有锁,也没有办法从线程A到线程B建立一个发生前关系,那么通过Java内存模型(JMM规范)线程B根本不能保证看到线程A对映像的任何更新...
所以我认为,最起码的解决方案是线程A和线程B都在同一个共享锁上定期同步,但在同步块内实际上不执行任何工作——这就是导致模式不标准和可疑的原因。要用半实半伪代码进行说明:
class ComputationCanvas extends java.awt.Canvas {
private Object lock = new Object();
private int[] pixels = new int[1000000];
public ComputationCanvas() {
new Thread(this::runThreadA).start();
new Thread(this::runThreadB).start();
}
private void runThreadA() {
while (true) {
for (1000 steps) {
update pixels directly
without synchornization
}
synchronized(lock) {} // Blank
}
}
private void runThreadB() {
while (true) {
Thread.sleep(100);
synchronized(lock) {} // Blank
this.repaint();
}
}
@Override
public void paint(Graphics g) {
g.drawImage(pixels, 0, 0);
}
}
以这种方式添加空同步块是否正确地实现了将html" target="_blank">数据从线程A传输到线程B的效果?还是有其他我无法想象的解决方案?
是的,很有效。但效果很糟糕。
只有当作者的释放发生在读者获得之前时,才会起作用。您的实现假设您正在编写的内容将在后续从ThreadB
读取/更新之前完成。让您的数据一直被synchronized刷新会导致性能问题,尽管我不能确定其程度。当然,您已经使同步更细粒度了,您测试过了吗?
更好的解决方案可能是使用singleton/transfer SPSC(单生产者/单消费者)队列来存储写入线程的当前快照,并在更新时使用该快照。
int[] data = ...
Queue<int[]> queue = new ...
// Thread A
while (true) {
for (1000 iterations or so) {
...
}
queue.add(data);
}
// Thread B
while (true) {
int[] snapshot = queue.take();
this.repaint();
}
这样做的好处是,你不需要忙碌等待,你可以等待队列阻塞或直到下一次写入。您可以跳过没有时间更新的写入。您不需要依赖于任意线程调度程序来为您规划数据刷新。
请记住,线程安全的数据结构非常适合在线程之间传递数据。
编辑:哎呀,忘了说,根据更新的进展情况,您可能希望使用数组副本来防止数据因未缓存的随机写入而被篡改。
问题内容: 我有一个奇怪的问题,如果可以解决,那就太好了。出于调试目的(以及其他一些目的),我在标准输出上编写了控制台Java应用程序的日志。在标准输出上写一些内容,在标准错误上打印一些错误,例如错误。问题是这两个没有完全同步,因此打印线的顺序并不总是正确的。我猜这是因为打印了很多东西,并且碰巧一个输出的缓冲区已满,所以其他输出在第一个输出刷新其缓冲区之前就已打印出来。 例如,我想这样写: 有时打
问题内容: 我有两个线程,我想确保我在LinkedBlockingQueue上正确进行了同步。这正确吗?还是不需要在(messageToCommsQueue)上进行显式同步? 宣言: 方法一: 方法二: 问题答案: 是的,没有必要。JavaDoc说: BlockingQueue实现是线程安全的。
问题内容: 有谁能举例说明同步方法优于同步块的优势吗? 问题答案: 在块上使用同步方法没有明显的优势。 也许唯一的一个(但我不会称其为优势)是你不需要包括对象引用。 方法: 块: 看到?完全没有优势。 但是,块确实比方法具有优势,主要是在灵活性方面,因为你可以将另一个对象用作锁,而同步该方法将锁定整个对象。 比较: 与 同样,如果方法变大,你仍然可以将同步部分分开:
我正在JBOSS中实现SP启动的web浏览器SAML SSO配置文件。 我的应用程序是SP。 登录后,我希望IDP向我发送以下格式的加密断言: 对于一些国内流离失所者来说效果很好,但现在我有了一个国内流离失所者,它向我发送: 并且由于签名丢失,身份验证失败。 我的问题是:是否有SAML 2.0加密断言的标准格式,我可以告诉IDP管理员使用它?还是我必须支持这两种方式? 谢谢
这个问题在我的项目中经常出现。作为一个例子,假设我有两个接口,一个从API检索信息,另一个解析这些信息。 现在,我可能需要有不同的API,因此我将有许多的实现,但每个实现都需要自己的。 这看起来与Bridge设计模式所建议的非常相似,但是该模式允许任何APIClient使用任何APIParser(我说的对吗?) 那么,有没有更好的解决方案呢?或者也许这很好,不需要重构它。 另外,也许parse不是
问题内容: 这是我正在考虑使用的模式: 通常,相对于dict get / set访问,我更喜欢对象属性访问的语义,但是在某些情况下,需要像dict一样的访问(例如),并且在这些情况下,我不希望使用特殊的gettersetter方法,因此,具有共享属性的dict和object同时具有双重行为。 是否有上述模式的陷阱? 问题答案: 这是达到相同效果的一种不太“ hacky”的方法: 我 认为 您的方法