minecraft-src/net/minecraft/server/rcon/thread/GenericThread.java
2025-07-04 01:41:11 +03:00

64 lines
1.8 KiB
Java

package net.minecraft.server.rcon.thread;
import com.mojang.logging.LogUtils;
import java.util.concurrent.atomic.AtomicInteger;
import net.minecraft.DefaultUncaughtExceptionHandlerWithName;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
public abstract class GenericThread implements Runnable {
private static final Logger LOGGER = LogUtils.getLogger();
private static final AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0);
private static final int MAX_STOP_WAIT = 5;
protected volatile boolean running;
protected final String name;
@Nullable
protected Thread thread;
protected GenericThread(String name) {
this.name = name;
}
public synchronized boolean start() {
if (this.running) {
return true;
} else {
this.running = true;
this.thread = new Thread(this, this.name + " #" + UNIQUE_THREAD_ID.incrementAndGet());
this.thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandlerWithName(LOGGER));
this.thread.start();
LOGGER.info("Thread {} started", this.name);
return true;
}
}
public synchronized void stop() {
this.running = false;
if (null != this.thread) {
int i = 0;
while (this.thread.isAlive()) {
try {
this.thread.join(1000L);
if (++i >= 5) {
LOGGER.warn("Waited {} seconds attempting force stop!", i);
} else if (this.thread.isAlive()) {
LOGGER.warn("Thread {} ({}) failed to exit after {} second(s)", this, this.thread.getState(), i, new Exception("Stack:"));
this.thread.interrupt();
}
} catch (InterruptedException var3) {
}
}
LOGGER.info("Thread {} stopped", this.name);
this.thread = null;
}
}
/**
* Returns {@code true} if the Thread is running, {@code false} otherwise.
*/
public boolean isRunning() {
return this.running;
}
}