diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java index 4be437a90..9651fcf7f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/DownloadProviders.java @@ -23,9 +23,12 @@ import javafx.beans.value.ObservableObjectValue; import org.jackhuang.hmcl.download.BMCLAPIDownloadProvider; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.MojangDownloadProvider; +import org.jackhuang.hmcl.task.Schedulers; +import org.jackhuang.hmcl.ui.FXUtils; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ThreadPoolExecutor; import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.util.Lang.mapOf; @@ -48,6 +51,10 @@ public final class DownloadProviders { () -> Optional.ofNullable(providersById.get(config().getDownloadType())) .orElse(providersById.get(DEFAULT_PROVIDER_ID)), config().downloadTypeProperty()); + + FXUtils.onChangeAndOperate(downloadProviderProperty, provider -> { + Schedulers.io().setMaximumPoolSize(provider.getConcurrency()); + }); } public static DownloadProvider getDownloadProvider() { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java index 918af71c5..61785cb2c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/BMCLAPIDownloadProvider.java @@ -90,4 +90,8 @@ public class BMCLAPIDownloadProvider implements DownloadProvider { .replace("https://authlib-injector.yushi.moe", apiRoot + "/mirrors/authlib-injector"); } + @Override + public int getConcurrency() { + return Math.max(Runtime.getRuntime().availableProcessors() * 2, 6); + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DownloadProvider.java index 582e98a5a..8492611e3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DownloadProvider.java @@ -56,4 +56,10 @@ public interface DownloadProvider { * @throws IllegalArgumentException if the version list does not exist */ VersionList getVersionListById(String id); + + /** + * The maximum download concurrency that this download provider supports. + * @return the maximum download concurrency. + */ + int getConcurrency(); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java index 94c25190b..870ec9e27 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MojangDownloadProvider.java @@ -76,4 +76,9 @@ public class MojangDownloadProvider implements DownloadProvider { public String injectURL(String baseURL) { return baseURL; } + + @Override + public int getConcurrency() { + return 6; + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java index d72214c30..849c8f453 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Schedulers.java @@ -22,16 +22,7 @@ import org.jackhuang.hmcl.util.Logging; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; /** @@ -43,9 +34,9 @@ public final class Schedulers { private Schedulers() { } - private static volatile ExecutorService CACHED_EXECUTOR; + private static volatile ThreadPoolExecutor CACHED_EXECUTOR; - public static synchronized Executor newThread() { + public static synchronized ThreadPoolExecutor newThread() { if (CACHED_EXECUTOR == null) CACHED_EXECUTOR = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new SynchronousQueue<>(), Executors.defaultThreadFactory()); @@ -53,22 +44,25 @@ public final class Schedulers { return CACHED_EXECUTOR; } - private static volatile ExecutorService IO_EXECUTOR; + private static volatile ThreadPoolExecutor IO_EXECUTOR; - public static synchronized Executor io() { + public static synchronized ThreadPoolExecutor io() { if (IO_EXECUTOR == null) - IO_EXECUTOR = Executors.newFixedThreadPool(6, runnable -> { - Thread thread = Executors.defaultThreadFactory().newThread(runnable); - thread.setDaemon(true); - return thread; - }); + IO_EXECUTOR = new ThreadPoolExecutor(0, 6, + 60L, TimeUnit.SECONDS, + new SynchronousQueue<>(), + runnable -> { + Thread thread = Executors.defaultThreadFactory().newThread(runnable); + thread.setDaemon(true); + return thread; + }); return IO_EXECUTOR; } private static volatile ExecutorService SINGLE_EXECUTOR; - public static synchronized Executor computation() { + public static synchronized ExecutorService computation() { if (SINGLE_EXECUTOR == null) SINGLE_EXECUTOR = Executors.newSingleThreadExecutor(runnable -> { Thread thread = Executors.defaultThreadFactory().newThread(runnable);