优化 Task 的资源占用 (#4694)
This commit is contained in:
@@ -345,16 +345,11 @@ public abstract class Task<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final ReadOnlyStringWrapper message = new ReadOnlyStringWrapper(this, "message", null);
|
private final ReadOnlyStringWrapper message = new ReadOnlyStringWrapper(this, "message", null);
|
||||||
private final InvocationDispatcher<String> messageUpdate = InvocationDispatcher.runOn(Platform::runLater, message::set);
|
|
||||||
|
|
||||||
public final ReadOnlyStringProperty messageProperty() {
|
public final ReadOnlyStringProperty messageProperty() {
|
||||||
return message.getReadOnlyProperty();
|
return message.getReadOnlyProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void updateMessage(String newMessage) {
|
|
||||||
messageUpdate.accept(newMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final T run() throws Exception {
|
public final T run() throws Exception {
|
||||||
if (getSignificance().shouldLog())
|
if (getSignificance().shouldLog())
|
||||||
LOG.trace("Executing task: " + getName());
|
LOG.trace("Executing task: " + getName());
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.util;
|
package org.jackhuang.hmcl.util;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.VarHandle;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/// When [#accept(T)] is called, this class invokes the handler on another thread.
|
/// When [#accept(T)] is called, this class invokes the handler on another thread.
|
||||||
@@ -28,6 +29,16 @@ import java.util.function.Consumer;
|
|||||||
/// @author yushijinhun
|
/// @author yushijinhun
|
||||||
public final class InvocationDispatcher<T> implements Consumer<T> {
|
public final class InvocationDispatcher<T> implements Consumer<T> {
|
||||||
|
|
||||||
|
private static final VarHandle PENDING_ARG_HANDLE;
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
PENDING_ARG_HANDLE = MethodHandles.lookup()
|
||||||
|
.findVarHandle(InvocationDispatcher.class, "pendingArg", Holder.class);
|
||||||
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
|
throw new ExceptionInInitializerError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// @param executor The executor must dispatch all tasks to a single thread.
|
/// @param executor The executor must dispatch all tasks to a single thread.
|
||||||
public static <T> InvocationDispatcher<T> runOn(Executor executor, Consumer<T> action) {
|
public static <T> InvocationDispatcher<T> runOn(Executor executor, Consumer<T> action) {
|
||||||
return new InvocationDispatcher<>(executor, action);
|
return new InvocationDispatcher<>(executor, action);
|
||||||
@@ -35,7 +46,10 @@ public final class InvocationDispatcher<T> implements Consumer<T> {
|
|||||||
|
|
||||||
private final Executor executor;
|
private final Executor executor;
|
||||||
private final Consumer<T> action;
|
private final Consumer<T> action;
|
||||||
private final AtomicReference<Holder<T>> pendingArg = new AtomicReference<>();
|
|
||||||
|
/// @see #PENDING_ARG_HANDLE
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private volatile Holder<T> pendingArg;
|
||||||
|
|
||||||
private InvocationDispatcher(Executor executor, Consumer<T> action) {
|
private InvocationDispatcher(Executor executor, Consumer<T> action) {
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
@@ -44,12 +58,15 @@ public final class InvocationDispatcher<T> implements Consumer<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(T t) {
|
public void accept(T t) {
|
||||||
if (pendingArg.getAndSet(new Holder<>(t)) == null) {
|
if (PENDING_ARG_HANDLE.getAndSet(this, new Holder<>(t)) == null) {
|
||||||
executor.execute(() -> {
|
executor.execute(() -> {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
var holder = (Holder<T>) PENDING_ARG_HANDLE.getAndSet(this, (Holder<T>) null);
|
||||||
|
|
||||||
// If the executor supports multiple underlying threads,
|
// If the executor supports multiple underlying threads,
|
||||||
// we need to add synchronization, but for now we can omit it :)
|
// we need to add synchronization, but for now we can omit it :)
|
||||||
// synchronized (InvocationDispatcher.this)
|
// synchronized (InvocationDispatcher.this)
|
||||||
action.accept(pendingArg.getAndSet(null).value);
|
action.accept(holder.value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user