-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(all): tune single Thread into SingleThreadExecutor #5410
Changes from 2 commits
dbbb75d
5708796
d92bcca
3ac0795
87c1b5d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package org.tron.common.es; | ||
|
||
import com.google.common.util.concurrent.ThreadFactoryBuilder; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.ScheduledExecutorService; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@Slf4j(topic = "common") | ||
public class ExecutorServiceManager { | ||
|
||
public static ExecutorService newSingleThreadExecutor(String name) { | ||
return newSingleThreadExecutor(name, false); | ||
} | ||
|
||
public static ExecutorService newSingleThreadExecutor(String name, boolean isDaemon) { | ||
return Executors.newSingleThreadExecutor( | ||
new ThreadFactoryBuilder().setNameFormat(name).setDaemon(isDaemon).build()); | ||
} | ||
|
||
|
||
public static ScheduledExecutorService newSingleThreadScheduledExecutor(String name) { | ||
return newSingleThreadScheduledExecutor(name, false); | ||
} | ||
|
||
public static ScheduledExecutorService newSingleThreadScheduledExecutor(String name, | ||
boolean isDaemon) { | ||
return Executors.newSingleThreadScheduledExecutor( | ||
new ThreadFactoryBuilder().setNameFormat(name).setDaemon(isDaemon).build()); | ||
} | ||
|
||
public static void shutdownAndAwaitTermination(ExecutorService pool, String name) { | ||
if (pool == null) { | ||
return; | ||
} | ||
pool.shutdown(); // Disable new tasks from being submitted | ||
try { | ||
// Wait a while for existing tasks to terminate | ||
if (!pool.awaitTermination(60, java.util.concurrent.TimeUnit.SECONDS)) { | ||
pool.shutdownNow(); // Cancel currently executing tasks | ||
// Wait a while for tasks to respond to being cancelled | ||
if (!pool.awaitTermination(60, java.util.concurrent.TimeUnit.SECONDS)) { | ||
logger.warn("Pool {} did not terminate", name); | ||
} | ||
} | ||
} catch (InterruptedException ie) { | ||
// (Re-)Cancel if current thread also interrupted | ||
pool.shutdownNow(); | ||
// Preserve interrupt status | ||
Thread.currentThread().interrupt(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,12 +3,14 @@ | |
import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; | ||
|
||
import com.google.protobuf.ByteString; | ||
import java.util.concurrent.ExecutorService; | ||
import lombok.Setter; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.joda.time.DateTime; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.util.StringUtils; | ||
import org.springframework.util.ObjectUtils; | ||
import org.tron.common.es.ExecutorServiceManager; | ||
import org.tron.common.parameter.CommonParameter; | ||
import org.tron.common.utils.ByteArray; | ||
import org.tron.common.utils.Sha256Hash; | ||
|
@@ -34,16 +36,18 @@ public class DposTask { | |
@Setter | ||
private DposService dposService; | ||
|
||
private Thread produceThread; | ||
private ExecutorService produceExecutor; | ||
|
||
private final String name = "DPosMiner"; | ||
|
||
private volatile boolean isRunning = true; | ||
|
||
public void init() { | ||
|
||
if (!dposService.isEnable() || StringUtils.isEmpty(dposService.getMiners())) { | ||
if (!dposService.isEnable() || ObjectUtils.isEmpty(dposService.getMiners())) { | ||
return; | ||
} | ||
|
||
produceExecutor = ExecutorServiceManager.newSingleThreadExecutor(name); | ||
Runnable runnable = () -> { | ||
while (isRunning) { | ||
try { | ||
|
@@ -67,17 +71,15 @@ public void init() { | |
} | ||
} | ||
}; | ||
produceThread = new Thread(runnable, "DPosMiner"); | ||
produceThread.start(); | ||
produceExecutor.submit(runnable); | ||
logger.info("DPoS task started."); | ||
} | ||
|
||
public void stop() { | ||
logger.info("DPoS task shutdown..."); | ||
isRunning = false; | ||
if (produceThread != null) { | ||
produceThread.interrupt(); | ||
} | ||
logger.info("DPoS task stopped."); | ||
ExecutorServiceManager.shutdownAndAwaitTermination(produceExecutor, name); | ||
logger.info("DPoS task shutdown complete"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can the thread shutdown log be printed in the function shutdownAndAwaitTermination? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, Great! |
||
} | ||
|
||
private State produceBlock() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,6 +49,7 @@ | |
import org.tron.api.GrpcAPI.TransactionInfoList; | ||
import org.tron.common.args.GenesisBlock; | ||
import org.tron.common.bloom.Bloom; | ||
import org.tron.common.es.ExecutorServiceManager; | ||
import org.tron.common.logsfilter.EventPluginLoader; | ||
import org.tron.common.logsfilter.FilterQuery; | ||
import org.tron.common.logsfilter.capsule.BlockFilterCapsule; | ||
|
@@ -253,6 +254,13 @@ public class Manager { | |
private AtomicInteger blockWaitLock = new AtomicInteger(0); | ||
private Object transactionLock = new Object(); | ||
|
||
private ExecutorService rePushEs; | ||
private static final String rePushEsName = "repush"; | ||
private ExecutorService triggerEs; | ||
private static final String triggerEsName = "event-trigger"; | ||
private ExecutorService filterEs; | ||
private static final String filterEsName = "filter"; | ||
|
||
/** | ||
* Cycle thread to rePush Transactions | ||
*/ | ||
|
@@ -429,14 +437,17 @@ public BlockingQueue<TransactionCapsule> getRePushTransactions() { | |
|
||
public void stopRePushThread() { | ||
isRunRePushThread = false; | ||
ExecutorServiceManager.shutdownAndAwaitTermination(rePushEs, rePushEsName); | ||
} | ||
|
||
public void stopRePushTriggerThread() { | ||
isRunTriggerCapsuleProcessThread = false; | ||
ExecutorServiceManager.shutdownAndAwaitTermination(triggerEs, triggerEsName); | ||
} | ||
|
||
public void stopFilterProcessThread() { | ||
isRunFilterProcessThread = false; | ||
ExecutorServiceManager.shutdownAndAwaitTermination(filterEs, filterEsName); | ||
} | ||
|
||
@PostConstruct | ||
|
@@ -524,21 +535,19 @@ public void init() { | |
revokingStore.enable(); | ||
validateSignService = Executors | ||
.newFixedThreadPool(Args.getInstance().getValidateSignThreadNum()); | ||
Thread rePushThread = new Thread(rePushLoop); | ||
rePushThread.setDaemon(true); | ||
rePushThread.start(); | ||
rePushEs = ExecutorServiceManager.newSingleThreadExecutor(rePushEsName, true); | ||
rePushEs.submit(rePushLoop); | ||
// add contract event listener for subscribing | ||
if (Args.getInstance().isEventSubscribe()) { | ||
startEventSubscribing(); | ||
Thread triggerCapsuleProcessThread = new Thread(triggerCapsuleProcessLoop); | ||
triggerCapsuleProcessThread.setDaemon(true); | ||
triggerCapsuleProcessThread.start(); | ||
triggerEs = ExecutorServiceManager.newSingleThreadExecutor(triggerEsName, true); | ||
triggerEs.submit(triggerCapsuleProcessLoop); | ||
} | ||
|
||
// start json rpc filter process | ||
if (CommonParameter.getInstance().isJsonRpcFilterEnabled()) { | ||
Thread filterProcessThread = new Thread(filterProcessLoop); | ||
filterProcessThread.start(); | ||
filterEs = ExecutorServiceManager.newSingleThreadExecutor(filterEsName, true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. isDaemon original default value is false |
||
filterEs.submit(filterProcessLoop); | ||
} | ||
|
||
//initStoreFactory | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package org.tron.common.backup; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import org.junit.After; | ||
import org.junit.Before; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.junit.rules.TemporaryFolder; | ||
import org.tron.common.backup.socket.BackupServer; | ||
import org.tron.common.parameter.CommonParameter; | ||
import org.tron.core.Constant; | ||
import org.tron.core.config.args.Args; | ||
|
||
|
||
public class BackupServerTest { | ||
|
||
@Rule | ||
public TemporaryFolder temporaryFolder = new TemporaryFolder(); | ||
private BackupServer backupServer; | ||
|
||
@Before | ||
public void setUp() throws Exception { | ||
Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()}, Constant.TEST_CONF); | ||
CommonParameter.getInstance().setBackupPort(80); | ||
List<String> members = new ArrayList<>(); | ||
members.add("127.0.0.2"); | ||
CommonParameter.getInstance().setBackupMembers(members); | ||
BackupManager backupManager = new BackupManager(); | ||
backupManager.init(); | ||
backupServer = new BackupServer(backupManager); | ||
} | ||
|
||
@After | ||
public void tearDown() { | ||
backupServer.close(); | ||
Args.clearParam(); | ||
} | ||
|
||
@Test | ||
public void test() throws InterruptedException { | ||
backupServer.initServer(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why there are two waits of 60s, will the 60s time be too long?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
60s is the maximum value to be waited until the pool stops, if it doesn't, the pool may have a problem executing the task and needs to be fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
copy from java.util.concurrent.ExecutorService