public abstract class OperationRunner extends Object
So the OperationExecutor
is responsible for 'executing' them
(so finding a thread to run on), the actual work is done by the
OperationRunner
. This separation of concerns makes the code a
lot simpler and makes it possible to swap parts of the system.
Since HZ 3.5 there are multiple OperationRunner instances; each partition will have its own OperationRunner, but also generic threads will have their own OperationRunners. Each OperationRunner exposes the Operation it is currently working on and this makes it possible to hook on all kinds of additional functionality like detecting slow operations, sampling which operations are executed most frequently, check if an operation is still running, etc etc.
Modifier and Type | Field and Description |
---|---|
protected Object |
currentTask |
protected int |
partitionId |
Constructor and Description |
---|
OperationRunner(int partitionId) |
Modifier and Type | Method and Description |
---|---|
Object |
currentTask()
Returns the current task that is executing.
|
Thread |
currentThread()
Get the thread that is currently running this OperationRunner
instance.
|
abstract long |
executedOperationsCount() |
int |
getPartitionId()
Returns the partitionId this OperationRunner is responsible for.
|
abstract void |
run(Operation task) |
abstract void |
run(Packet packet) |
abstract void |
run(Runnable task) |
void |
setCurrentThread(Thread currentThread)
Sets the thread that is running this OperationRunner instance.
|
protected final int partitionId
protected volatile Object currentTask
public abstract long executedOperationsCount()
public abstract void run(Runnable task)
public abstract void run(Operation task)
public final Object currentTask()
Value could be stale as soon as it is returned.
This method is thread-safe; so the thread that executes a task will set/unset the current task, any other thread in the system is allowed to read it.
public final void setCurrentThread(Thread currentThread)
This method should only be called from the OperationExecutor
since this component is responsible for executing operations on an
OperationRunner.
currentThread
- the current Thread. Can be called with 'null',
clearing the currentThread field.public final Thread currentThread()
This value only has meaning when an Operation is running. It depends on the implementation if the field is unset after an operation is executed or not. So it could be that a value is returned while no operation is running.
For example, the OperationExecutorImpl
will never unset this
field since each OperationRunner is bound to a single OperationThread;
so this field is initialized when the OperationRunner is created.
The returned value could be null. When it is null, currently no thread is running this OperationRunner.
Recommended idiom for slow operation detection: 1: First read the operation and store the reference. 2: Then read the current thread and store the reference 3: Later read the operation again. If the operation-instance is the same, it means that you have captured the right thread.
Then you use this Thread to create a stack trace. It can happen that the stracktrace doesn't reflect the call-state the thread had when the slow operation was detected. This could be solved by rechecking the currentTask after you have detected the slow operation. BUt don't create a stacktrace before you do the first recheck of the operation because otherwise it will cause a lot of overhead.
public final int getPartitionId()
The value will never change for this OperationRunner instance.
Copyright © 2021 Hazelcast, Inc.. All Rights Reserved.