英文:
Java multi-thread switching context vs submit new task and solution for monitoring a queue
问题
关于在线程之间切换上下文(使用等待/通知进行同步)以及重新提交任务(Callable/Runnable)到Executor服务,哪种方式对性能更好呢?我知道切换上下文需要保存/加载线程数据,但是如果我重新提交一个任务到Executor服务,JVM需要重新分配已提交任务的栈,所以我认为它的成本与切换上下文是相同的。
我设计了一个任务队列,用于工作线程将任务放入队列,并有一个监视线程从队列中取出任务,然后将任务提交给线程池(Executor服务)。但我在考虑监视线程何时工作的问题?
选项1:监视线程使用“等待”,工作线程在将任务放入队列后会通知监视线程。
选项2:为监视线程使用调度器Executor服务,以检查队列。
-> 哪个选项更好(就速度和性能而言)?对于选项2:多久检查一次队列最好?
非常感谢您的帮助。
英文:
-
About switching context (synchronizing with wait/notify) between threads and re-submit a task (Callable/Runnable) to Executor service which is better for performance? as I know switching context need to save/reload thread data but if I re-submit a task to an Executor service, JVM need to re-allocate stack for the submitted task so I think it has same cost with switching context?
-
I design a task queue for worker threads put tasks to that and a monitor thread to take the tasks in the queue, submit the tasks to a thread pool (executor service). But I considering about when does the monitor thread work?
Option 1: Using thread "wait" for monitor thread and worker thread will notify the monitor thread after they put task to the queue.
Option 2: Using a scheduler executor service for monitor thread to check the queue.
-> Which option is better (for speed, performance) and with option 2: how often to check the queue is the best?
many thanks for your help
答案1
得分: 0
-
通常执行器由线程池支持。因此,堆栈已经分配好了。此外,只有在相同 CPU 核心必须执行两个线程时,才会进行上下文切换。现代 CPU 有多个核心,因此不会涉及上下文切换。
话虽如此,将工作传递到另一个线程中肯定会有一些开销。因此,任务应足够粗粒度,并且主线程可以在此期间执行其他工作,以使线程池具有益处。
-
如果队列本身已同步,就不需要有监视器线程。例如,可以查看
ArrayBlockingQueue
;生产者可以调用put()
方法(在队列没有可用空间时会阻塞),消费者(池中的线程)调用take()
,在没有可用工作时会阻塞。这就是ThreadPoolExecutor
的实现方式(确切地说,它实际上调用了offer()
,因此默认情况下在生产者端不会阻塞)。
英文:
-
An executor is usually backed by a thread pool. So the stacks are already allocated. Furthermore, a context switch will only take place if the same CPU core has to execute both threads. Modern CPUs have multiple cores, so there would be no context switch involved.
Having said that, there is surely some overhead in transferring work to another thread. So tasks should be sufficiently coarse-grained and there should be other work that the main thread can perform in the meantime for the pool to be beneficial.
-
There is no need to have a monitor thread if the queue itself is synchronized. Have a look at
ArrayBlockingQueue
for example; producers can call theput()
method (which blocks when no space in the queue is available), and consumers (threads in the pool) calltake()
, which blocks when no work is available. This is howThreadPoolExecutor
is implemented (to be precise, it actually callsoffer()
, so by default doesn't block on the producer side).
专注分享java语言的经验与见解,让所有开发者获益!
评论