我有一个问题,但与我在这里的第一个问题不完全相同:
Java: what happens when a new Thread is started from a synchronized block?
当您持有锁定时,创建start()
新Thread
这是一种常见做法吗?
这会是代码味吗?
基本上我可以选择这样做:
public synchronized void somemethod() {
(every time I find a callback to be notified I start a thread)
Thread t = new Thread( new Runnable() {
void run() {
notifySomeCallback();
}
}
t.start();
...
(lengthy stuff performed here, keeping the lock held)
...
}
或者这个:
public void somemethod() {
(create a list of callbacks to be notified)
synchronized(this){
(potentially add callbacks)
...
(lengthy stuff performed here, keeping the lock held)
...
}
(notify the callbacks without holding a lock and once
we know the lock has been released)
}
我认为后者更好但我想知道是否存在 是第一种选择可以的情况?你有时候吗? 去做?你见过它吗?
答案 0 :(得分:4)
ANSWER3:
您应该始终保持锁定尽可能短。因此,当存在“损坏”资源的可能性时(例如,写入程序线程正在更新资源),只有在多个线程中可能引用的资源应该被锁定最短的时间
不要为每个需要完成的小事件分离一个线程。在回调线程的情况下,让一个回调线程处理一系列事情。
答案 1 :(得分:3)
您知道这两个代码段将导致不同的执行顺序。 第一个将异步运行回调,而正在执行冗长的东西。第二个将首先完成冗长的工作,然后调用回调。
哪一个更好取决于回调需要做什么。如果他们需要首先完成冗长的工作,这可能是一个问题。
谁在等锁? 如果回调需要锁定运行,那么在你仍然保持锁定时触发它们是没有意义的。他们所要做的只是等待很长时间才能完成。
此外,在第一个代码段中,每个回调都有一个主题。第二个片段不明确,但如果你只有一个线程,这是另一个区别 (回调是同时运行还是按顺序运行)。如果他们都需要相同的锁,你也可以按顺序运行它们。
如果要使用一个或多个线程运行多个回调,请考虑使用Executor而不是自己管理线程。使配置适当数量的线程变得非常容易。
答案 2 :(得分:2)
这取决于你是否希望回调与冗长的东西同时执行。如果我们讨论的是Swing GUI,那么选项1并不好,因为你不应该在几个并发线程中进行Swing操作,所以我建议如下:
public void somemethod() {
Thread t = new Thread( new Runnable() {
void run() {
synchronized(this) {
doLengthyStuff();
}
}
}
t.start();
(notify the callbacks)
}