diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java index 7aec0298a..55e36892e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java @@ -105,7 +105,8 @@ public final class WorldEdit { private final PlatformManager platformManager = new PlatformManager(this); private final EditSessionFactory editSessionFactory = new EditSessionFactory.EditSessionFactoryImpl(eventBus); private final SessionManager sessions = new SessionManager(this); - private final ListeningExecutorService executorService = MoreExecutors.listeningDecorator(EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 20));; + private final ListeningExecutorService executorService = MoreExecutors.listeningDecorator( + EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 20, "WorldEdit Task Executor - %s")); private final Supervisor supervisor = new SimpleSupervisor(); private final BlockFactory blockFactory = new BlockFactory(this); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java index 61110ea09..948bbe444 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java @@ -54,6 +54,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -177,7 +178,8 @@ public class MCEditSchematicReader extends NBTSchematicReader { } // Need to pull out tile entities - List tileEntities = requireTag(schematic, "TileEntities", ListTag.class).getValue(); + final ListTag tileEntityTag = getTag(schematic, "TileEntities", ListTag.class); + List tileEntities = tileEntityTag == null ? new ArrayList<>() : tileEntityTag.getValue(); Map> tileEntitiesMap = new HashMap<>(); Map blockStates = new HashMap<>(); @@ -245,7 +247,7 @@ public class MCEditSchematicReader extends NBTSchematicReader { byte data = blockData[index]; int combined = block << 8 | data; if (unknownBlocks.add(combined)) { - log.warn("Unknown block when pasting schematic: " + log.warn("Unknown block when loading schematic: " + block + ":" + data + ". Please report this issue."); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java index 403d874c5..ef346d429 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java @@ -19,6 +19,8 @@ package com.sk89q.worldedit.session; +import static com.google.common.base.Preconditions.checkNotNull; + import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; @@ -55,8 +57,6 @@ import java.util.TimerTask; import java.util.UUID; import java.util.concurrent.Callable; -import static com.google.common.base.Preconditions.checkNotNull; - /** * Session manager for WorldEdit. * @@ -68,11 +68,12 @@ public class SessionManager { public static int EXPIRATION_GRACE = 10 * 60 * 1000; private static final int FLUSH_PERIOD = 1000 * 30; - private static final ListeningExecutorService executorService = MoreExecutors.listeningDecorator(EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 5)); + private static final ListeningExecutorService executorService = MoreExecutors.listeningDecorator( + EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 5, "WorldEdit Session Saver - %s")); private static final Logger log = LoggerFactory.getLogger(SessionManager.class); private static boolean warnedInvalidTool; - private final Timer timer = new Timer(); + private final Timer timer = new Timer("WorldEdit Session Manager"); private final WorldEdit worldEdit; private final Map sessions = new HashMap<>(); private SessionStore store = new VoidStore(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/concurrency/EvenMoreExecutors.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/concurrency/EvenMoreExecutors.java index 5272039a1..1c40c9454 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/concurrency/EvenMoreExecutors.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/concurrency/EvenMoreExecutors.java @@ -19,8 +19,10 @@ package com.sk89q.worldedit.util.concurrency; -import java.util.concurrent.ArrayBlockingQueue; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -39,15 +41,33 @@ public final class EvenMoreExecutors { * * @param minThreads the minimum number of threads to have at a given time * @param maxThreads the maximum number of threads to have at a given time - * @param queueSize the size of the queue before new submissions are rejected + * @param queueSize the size of the queue before new submissions are rejected * @return the newly created thread pool */ public static ExecutorService newBoundedCachedThreadPool(int minThreads, int maxThreads, int queueSize) { + return newBoundedCachedThreadPool(minThreads, maxThreads, queueSize, null); + } + + /** + * Creates a thread pool that creates new threads as needed up to + * a maximum number of threads, but will reuse previously constructed + * threads when they are available. + * + * @param minThreads the minimum number of threads to have at a given time + * @param maxThreads the maximum number of threads to have at a given time + * @param queueSize the size of the queue before new submissions are rejected + * @param threadFormat thread name formatter + * @return the newly created thread pool + */ + public static ExecutorService newBoundedCachedThreadPool(int minThreads, int maxThreads, int queueSize, String threadFormat) { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( minThreads, maxThreads, 60L, TimeUnit.SECONDS, - new ArrayBlockingQueue<>(queueSize)); + new LinkedBlockingDeque<>(queueSize)); threadPoolExecutor.allowCoreThreadTimeOut(true); + if (threadFormat != null) { + threadPoolExecutor.setThreadFactory(new ThreadFactoryBuilder().setNameFormat(threadFormat).build()); + } return threadPoolExecutor; }