diff --git a/common/src/main/java/bisq/common/persistence/PersistenceManager.java b/common/src/main/java/bisq/common/persistence/PersistenceManager.java index 77a777d820..c786edf10a 100644 --- a/common/src/main/java/bisq/common/persistence/PersistenceManager.java +++ b/common/src/main/java/bisq/common/persistence/PersistenceManager.java @@ -26,8 +26,8 @@ import bisq.common.file.FileUtil; import bisq.common.handlers.ResultHandler; import bisq.common.proto.persistable.PersistableEnvelope; import bisq.common.proto.persistable.PersistenceProtoResolver; +import bisq.common.util.SingleThreadExecutorUtils; import bisq.common.util.GcUtil; -import bisq.common.util.Utilities; import com.google.inject.Inject; @@ -517,7 +517,7 @@ public class PersistenceManager { private ExecutorService getWriteToDiskExecutor() { if (writeToDiskExecutor == null) { String name = "Write-" + fileName + "_to-disk"; - writeToDiskExecutor = Utilities.getSingleThreadExecutor(name); + writeToDiskExecutor = SingleThreadExecutorUtils.getSingleThreadExecutor(name); } return writeToDiskExecutor; } diff --git a/common/src/main/java/bisq/common/util/SingleThreadExecutorUtils.java b/common/src/main/java/bisq/common/util/SingleThreadExecutorUtils.java new file mode 100644 index 0000000000..870c0c3f42 --- /dev/null +++ b/common/src/main/java/bisq/common/util/SingleThreadExecutorUtils.java @@ -0,0 +1,62 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.common.util; + +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; + +public class SingleThreadExecutorUtils { + public static ExecutorService getSingleThreadExecutor(Class aClass) { + String name = aClass.getSimpleName(); + return getSingleThreadExecutor(name); + } + + public static ExecutorService getNonDaemonSingleThreadExecutor(Class aClass) { + String name = aClass.getSimpleName(); + return getSingleThreadExecutor(name, false); + } + + public static ExecutorService getSingleThreadExecutor(String name) { + return getSingleThreadExecutor(name, true); + } + + public static ListeningExecutorService getSingleThreadListeningExecutor(String name) { + return MoreExecutors.listeningDecorator(getSingleThreadExecutor(name)); + } + + public static ExecutorService getSingleThreadExecutor(ThreadFactory threadFactory) { + return Executors.newSingleThreadExecutor(threadFactory); + } + + private static ExecutorService getSingleThreadExecutor(String name, boolean isDaemonThread) { + final ThreadFactory threadFactory = getThreadFactory(name, isDaemonThread); + return Executors.newSingleThreadExecutor(threadFactory); + } + + private static ThreadFactory getThreadFactory(String name, boolean isDaemonThread) { + return new ThreadFactoryBuilder() + .setNameFormat(name) + .setDaemon(isDaemonThread) + .build(); + } +} diff --git a/common/src/main/java/bisq/common/util/Utilities.java b/common/src/main/java/bisq/common/util/Utilities.java index 7acf8b6dfc..30e0e7a05f 100644 --- a/common/src/main/java/bisq/common/util/Utilities.java +++ b/common/src/main/java/bisq/common/util/Utilities.java @@ -84,45 +84,11 @@ import static com.google.common.base.Preconditions.checkNotNull; @Slf4j public class Utilities { - public static ExecutorService getSingleThreadExecutor(Class aClass) { - String name = aClass.getSimpleName(); - return getSingleThreadExecutor(name); - } - - public static ExecutorService getNonDaemonSingleThreadExecutor(Class aClass) { - String name = aClass.getSimpleName(); - return getSingleThreadExecutor(name, false); - } - - public static ExecutorService getSingleThreadExecutor(String name) { - return getSingleThreadExecutor(name, true); - } - - private static ExecutorService getSingleThreadExecutor(String name, boolean isDaemonThread) { - final ThreadFactory threadFactory = getThreadFactory(name, isDaemonThread); - return Executors.newSingleThreadExecutor(threadFactory); - } - - private static ThreadFactory getThreadFactory(String name, boolean isDaemonThread) { - return new ThreadFactoryBuilder() - .setNameFormat(name) - .setDaemon(isDaemonThread) - .build(); - } - - public static ExecutorService getSingleThreadExecutor(ThreadFactory threadFactory) { - return Executors.newSingleThreadExecutor(threadFactory); - } - public static ExecutorService getFixedThreadPoolExecutor(int nThreads, ThreadFactory threadFactory) { return Executors.newFixedThreadPool(nThreads, threadFactory); } - public static ListeningExecutorService getSingleThreadListeningExecutor(String name) { - return MoreExecutors.listeningDecorator(getSingleThreadExecutor(name)); - } - public static ListeningExecutorService getListeningExecutorService(String name, int corePoolSize, int maximumPoolSize, diff --git a/core/src/main/java/bisq/core/api/CoreWalletsService.java b/core/src/main/java/bisq/core/api/CoreWalletsService.java index 149a18d655..204a9e44a9 100644 --- a/core/src/main/java/bisq/core/api/CoreWalletsService.java +++ b/core/src/main/java/bisq/core/api/CoreWalletsService.java @@ -49,7 +49,7 @@ import bisq.core.util.coin.CoinFormatter; import bisq.common.Timer; import bisq.common.UserThread; import bisq.common.handlers.ResultHandler; -import bisq.common.util.Utilities; +import bisq.common.util.SingleThreadExecutorUtils; import org.bitcoinj.core.Address; import org.bitcoinj.core.Coin; @@ -116,7 +116,7 @@ class CoreWalletsService { @Nullable private KeyParameter tempAesKey; - private final ListeningExecutorService executor = Utilities.getSingleThreadListeningExecutor("CoreWalletsService"); + private final ListeningExecutorService executor = SingleThreadExecutorUtils.getSingleThreadListeningExecutor("CoreWalletsService"); @Inject public CoreWalletsService(AppStartupState appStartupState, diff --git a/core/src/main/java/bisq/core/app/BisqHeadlessAppMain.java b/core/src/main/java/bisq/core/app/BisqHeadlessAppMain.java index c5923b0528..410c0a908c 100644 --- a/core/src/main/java/bisq/core/app/BisqHeadlessAppMain.java +++ b/core/src/main/java/bisq/core/app/BisqHeadlessAppMain.java @@ -22,7 +22,7 @@ import bisq.core.payment.TradeLimits; import bisq.common.UserThread; import bisq.common.app.AppModule; import bisq.common.app.Version; -import bisq.common.util.Utilities; +import bisq.common.util.SingleThreadExecutorUtils; import java.util.concurrent.ExecutorService; @@ -60,7 +60,7 @@ public class BisqHeadlessAppMain extends BisqExecutable { @Override protected void configUserThread() { - ExecutorService executorService = Utilities.getSingleThreadExecutor(this.getClass()); + ExecutorService executorService = SingleThreadExecutorUtils.getSingleThreadExecutor(this.getClass()); UserThread.setExecutor(executorService); } diff --git a/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java b/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java index 7d72c197ae..29e13e6152 100644 --- a/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java +++ b/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java @@ -39,8 +39,8 @@ import bisq.common.file.JsonFileManager; import bisq.common.handlers.ResultHandler; import bisq.common.persistence.PersistenceManager; import bisq.common.setup.GracefulShutDownHandler; +import bisq.common.util.SingleThreadExecutorUtils; import bisq.common.util.Profiler; -import bisq.common.util.Utilities; import java.time.Instant; import java.time.ZoneId; @@ -69,7 +69,7 @@ public abstract class ExecutableForAppWithP2p extends BisqExecutable { @Override protected void configUserThread() { - ExecutorService executorService = Utilities.getSingleThreadExecutor(this.getClass()); + ExecutorService executorService = SingleThreadExecutorUtils.getSingleThreadExecutor(this.getClass()); UserThread.setExecutor(executorService); } diff --git a/core/src/main/java/bisq/core/dao/node/full/RpcService.java b/core/src/main/java/bisq/core/dao/node/full/RpcService.java index 2412e4e356..72c1401dc9 100644 --- a/core/src/main/java/bisq/core/dao/node/full/RpcService.java +++ b/core/src/main/java/bisq/core/dao/node/full/RpcService.java @@ -31,7 +31,7 @@ import bisq.core.user.Preferences; import bisq.common.UserThread; import bisq.common.config.Config; import bisq.common.handlers.ResultHandler; -import bisq.common.util.Utilities; +import bisq.common.util.SingleThreadExecutorUtils; import org.bitcoinj.core.Utils; @@ -91,7 +91,7 @@ public class RpcService { // We could use multiple threads, but then we need to support ordering of results in a queue // Keep that for optimization after measuring performance differences - private final ListeningExecutorService executor = Utilities.getSingleThreadListeningExecutor("RpcService"); + private final ListeningExecutorService executor = SingleThreadExecutorUtils.getSingleThreadListeningExecutor("RpcService"); private volatile boolean shutdownInProgress; private final Set setupResultHandlers = new CopyOnWriteArraySet<>(); private final Set> setupErrorHandlers = new CopyOnWriteArraySet<>(); diff --git a/core/src/main/java/bisq/core/dao/node/full/rpc/BitcoindDaemon.java b/core/src/main/java/bisq/core/dao/node/full/rpc/BitcoindDaemon.java index 8da2d8b895..1103e6dab7 100644 --- a/core/src/main/java/bisq/core/dao/node/full/rpc/BitcoindDaemon.java +++ b/core/src/main/java/bisq/core/dao/node/full/rpc/BitcoindDaemon.java @@ -17,6 +17,7 @@ package bisq.core.dao.node.full.rpc; +import bisq.common.util.SingleThreadExecutorUtils; import bisq.common.util.Utilities; import com.google.common.annotations.VisibleForTesting; @@ -43,7 +44,7 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class BitcoindDaemon { - private final ListeningExecutorService executor = Utilities.getSingleThreadListeningExecutor("block-notification-server"); + private final ListeningExecutorService executor = SingleThreadExecutorUtils.getSingleThreadListeningExecutor("block-notification-server"); private final ListeningExecutorService workerPool = Utilities.getListeningExecutorService("block-notification-worker", 1, 10, 60, new ArrayBlockingQueue<>(100)); private final ServerSocket serverSocket; diff --git a/core/src/main/java/bisq/core/dao/state/storage/DaoStateStorageService.java b/core/src/main/java/bisq/core/dao/state/storage/DaoStateStorageService.java index b3419418af..fcb2ffbaca 100644 --- a/core/src/main/java/bisq/core/dao/state/storage/DaoStateStorageService.java +++ b/core/src/main/java/bisq/core/dao/state/storage/DaoStateStorageService.java @@ -28,8 +28,8 @@ import bisq.common.UserThread; import bisq.common.config.Config; import bisq.common.file.FileUtil; import bisq.common.persistence.PersistenceManager; +import bisq.common.util.SingleThreadExecutorUtils; import bisq.common.util.GcUtil; -import bisq.common.util.Utilities; import javax.inject.Inject; import javax.inject.Named; @@ -55,7 +55,7 @@ public class DaoStateStorageService extends StoreService { private final BsqBlocksStorageService bsqBlocksStorageService; private final File storageDir; private final LinkedList blocks = new LinkedList<>(); - private final ExecutorService executorService = Utilities.getNonDaemonSingleThreadExecutor(this.getClass()); + private final ExecutorService executorService = SingleThreadExecutorUtils.getNonDaemonSingleThreadExecutor(this.getClass()); private Optional> future = Optional.empty(); diff --git a/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsConverter.java b/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsConverter.java index f360dd5557..c785368208 100644 --- a/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsConverter.java +++ b/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsConverter.java @@ -28,7 +28,7 @@ import bisq.network.p2p.storage.persistence.AppendOnlyDataStoreService; import bisq.common.UserThread; import bisq.common.config.Config; import bisq.common.file.FileUtil; -import bisq.common.util.Utilities; +import bisq.common.util.SingleThreadExecutorUtils; import com.google.inject.Inject; @@ -71,7 +71,7 @@ public class TradeStatisticsConverter { if (!tradeStatistics2Store.exists()) { return; } - executor = Utilities.getSingleThreadExecutor("TradeStatisticsConverter"); + executor = SingleThreadExecutorUtils.getSingleThreadExecutor("TradeStatisticsConverter"); executor.submit(() -> { // We convert early once tor is initialized but still not ready to receive data Map tempMap = new HashMap<>(); diff --git a/daemon/src/main/java/bisq/daemon/app/BisqDaemonMain.java b/daemon/src/main/java/bisq/daemon/app/BisqDaemonMain.java index 7fe4b633a3..9c24e26fb5 100644 --- a/daemon/src/main/java/bisq/daemon/app/BisqDaemonMain.java +++ b/daemon/src/main/java/bisq/daemon/app/BisqDaemonMain.java @@ -24,7 +24,7 @@ import bisq.core.app.CoreModule; import bisq.common.UserThread; import bisq.common.app.AppModule; import bisq.common.handlers.ResultHandler; -import bisq.common.util.Utilities; +import bisq.common.util.SingleThreadExecutorUtils; import java.util.concurrent.ExecutorService; @@ -49,7 +49,7 @@ public class BisqDaemonMain extends BisqHeadlessAppMain implements BisqSetup.Bis @Override protected void configUserThread() { - ExecutorService executorService = Utilities.getSingleThreadExecutor(this.getClass()); + ExecutorService executorService = SingleThreadExecutorUtils.getSingleThreadExecutor(this.getClass()); UserThread.setExecutor(executorService); } diff --git a/p2p/src/main/java/bisq/network/Socks5DnsDiscovery.java b/p2p/src/main/java/bisq/network/Socks5DnsDiscovery.java index ce66da8984..349e681445 100644 --- a/p2p/src/main/java/bisq/network/Socks5DnsDiscovery.java +++ b/p2p/src/main/java/bisq/network/Socks5DnsDiscovery.java @@ -17,6 +17,7 @@ package bisq.network; +import bisq.common.util.SingleThreadExecutorUtils; import bisq.common.util.Utilities; import org.bitcoinj.core.NetworkParameters; @@ -86,7 +87,7 @@ public class Socks5DnsDiscovery extends MultiplexingDiscovery { // Attempted workaround for reported bugs on Linux in which gethostbyname does not appear to be properly // thread safe and can cause segfaults on some libc versions. if (Utilities.isLinux()) - return Utilities.getSingleThreadExecutor(new ContextPropagatingThreadFactory("DNS seed lookups")); + return SingleThreadExecutorUtils.getSingleThreadExecutor(new ContextPropagatingThreadFactory("DNS seed lookups")); else return Utilities.getFixedThreadPoolExecutor(seeds.size(), new DaemonThreadFactory("DNS seed lookups")); } diff --git a/p2p/src/main/java/bisq/network/p2p/network/Connection.java b/p2p/src/main/java/bisq/network/p2p/network/Connection.java index 2bfeed9093..bafc38e7b6 100644 --- a/p2p/src/main/java/bisq/network/p2p/network/Connection.java +++ b/p2p/src/main/java/bisq/network/p2p/network/Connection.java @@ -40,6 +40,7 @@ import bisq.common.config.Config; import bisq.common.proto.ProtobufferException; import bisq.common.proto.network.NetworkEnvelope; import bisq.common.proto.network.NetworkProtoResolver; +import bisq.common.util.SingleThreadExecutorUtils; import bisq.common.util.Utilities; import com.google.protobuf.InvalidProtocolBufferException; @@ -133,7 +134,7 @@ public class Connection implements HasCapabilities, Runnable, MessageListener { private final NetworkFilter networkFilter; @Getter private final String uid; - private final ExecutorService singleThreadExecutor = Utilities.getSingleThreadExecutor(runnable -> new Thread(runnable, "Connection.java executor-service")); + private final ExecutorService singleThreadExecutor = SingleThreadExecutorUtils.getSingleThreadExecutor(runnable -> new Thread(runnable, "Connection.java executor-service")); @Getter private final Statistic statistic; @Getter diff --git a/p2p/src/main/java/bisq/network/p2p/network/NetworkNode.java b/p2p/src/main/java/bisq/network/p2p/network/NetworkNode.java index 71ad6632d7..a14ca25514 100644 --- a/p2p/src/main/java/bisq/network/p2p/network/NetworkNode.java +++ b/p2p/src/main/java/bisq/network/p2p/network/NetworkNode.java @@ -24,6 +24,7 @@ import bisq.common.UserThread; import bisq.common.app.Capabilities; import bisq.common.proto.network.NetworkEnvelope; import bisq.common.proto.network.NetworkProtoResolver; +import bisq.common.util.SingleThreadExecutorUtils; import bisq.common.util.Utilities; import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy; @@ -111,7 +112,7 @@ public abstract class NetworkNode implements MessageListener { maxConnections * 3, 30, 30); - serverExecutor = Utilities.getSingleThreadExecutor("NetworkNode.server-" + servicePort); + serverExecutor = SingleThreadExecutorUtils.getSingleThreadExecutor("NetworkNode.server-" + servicePort); } /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/p2p/src/main/java/bisq/network/p2p/network/TorNetworkNode.java b/p2p/src/main/java/bisq/network/p2p/network/TorNetworkNode.java index 1972e08b41..85835884bf 100644 --- a/p2p/src/main/java/bisq/network/p2p/network/TorNetworkNode.java +++ b/p2p/src/main/java/bisq/network/p2p/network/TorNetworkNode.java @@ -23,7 +23,7 @@ import bisq.network.utils.Utils; import bisq.common.Timer; import bisq.common.UserThread; import bisq.common.proto.network.NetworkProtoResolver; -import bisq.common.util.Utilities; +import bisq.common.util.SingleThreadExecutorUtils; import org.berndpruenster.netlayer.tor.HiddenServiceSocket; import org.berndpruenster.netlayer.tor.Tor; @@ -75,7 +75,7 @@ public class TorNetworkNode extends NetworkNode { this.torMode = torMode; this.streamIsolation = useStreamIsolation; - executor = Utilities.getSingleThreadExecutor("StartTor"); + executor = SingleThreadExecutorUtils.getSingleThreadExecutor("StartTor"); }