Я пытаюсь остановить операцию API в java, под которой я подразумеваю остановку процесса, который выполняется как часть вызова API. Мой апи выглядит так:
@RequestMapping(value = "/startProcess",method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> startProcess(
@Parameter(@RequestBody testBody)
) {
String somekindofID = testservice.startProcess();
return new ResponseEntity<>(someKindofID, HTTPStatus.OK);
}
@RequestMapping(value = "/testPID",method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> TestPID(
@Parameter(name = "somekindofID",required = true) @Valid @RequestBody String somekindofID)
) {
//get the ID from the above api and kill the running process
}
public String startProcess() {
long pid = 0;
new Thread(()-> {
try {
int exitCode = startProcessBuilderwithCommand(); //starts a processbuilder with batch file
if (exitCode != 0) {
return;
}else{
pid=consumer.initiateConsumer(); -> this is the process which needs to stop
}
} catch (Exception e) {
e.printStackTrace();
return;
}
}).start();
return pid;
}
Теперь я попытался использовать Java 9 ProcessHandle.current().pid()
но он дает PID самого приложения Java, который, если я использую для taskkill, завершит все приложение.
Есть ли способ получить идентификатор или что-то еще только из операции API, чтобы я мог завершить ее, не завершая все приложение Java?
Другими словами, я хотел бы завершить фоновый процесс, не убивая приложение.
P.S. метод testservice.startProcess() возвращает идентификатор метода initialconsumer(), который я пытаюсь убить, не убивая приложение
это прототип, у меня есть API, который запускает процесс в потоке, который я планирую использовать для возврата идентификатора, и я могу использовать этот идентификатор, чтобы остановить процесс API.
Вместо того, чтобы описывать части вашего кода в комментарии, почему бы не добавить код к вопросу. Но постарайтесь предоставить его как минимальный воспроизводимый пример - наименьшее количество кода, которое мы можем скопировать и запустить для себя, чтобы воссоздать ваш сценарий.
Я добавил отредактированный код, который можно воспроизвести.
поэтому, если вы возвращаете PID, если порожденный процесс, вам нужно написать другой API, чтобы вызывающая сторона могла его остановить? При этом уничтожение процесса в процессе выполнения работы может привести к непредсказуемому поведению. Поскольку мы не знаем, что делает этот процесс, кто знает, каковы будут результаты.
это не процесс, который я хочу убить, а Consumer.initiateConsumer(); запускает потребителя kafka, который работает в фоновом режиме. И я намерен остановить этого потребителя




По сути вам нужно следующее.
Потребитель, запущенный с помощью InitialConsumer(), должен содержать механизм, который он используется для проверки того, был ли он остановлен другим процессом.
способ определить, какого потребителя остановить.
@контроллер
@RequestMapping(value = "/startProcess", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Integer> startProcessPost(@RequestBody String testBody) {
int somekindofID = testservice.startProcess();
return new ResponseEntity<>(somekindofID, HttpStatus.OK);
}
@RequestMapping(value = "/testPID", method = RequestMethod.GET)
public ResponseEntity<Void> TestPID(@RequestParam(name = "somekindofID", required = true) int somekindofID) {
Consumer.killConsumer(somekindofID);
return new ResponseEntity<>(HttpStatus.OK);
}
Потребитель
public class Consumer {
private static Map<Integer, Consumer> runningConsumers = new HashMap<>();
boolean running;
public int initiateConsumer() {
running = true;
int hashCode = hashCode();
runningConsumers.put(hashCode, this);
// pass the work into a Runnable
return hashCode;
}
public static void killConsumer(int hashCode) {
Consumer consumerToBeKilled = runningConsumers.get(hashCode);
consumerToBeKilled.running = false;
}
private void consumerActivity() {
while(running) {
// keep working
}
// take me out of the Map
int hashCode = hashCode();
runningConsumers.remove(hashCode);
}
}
ТестСервис
public class TestService {
final Consumer consumer = new Consumer();
public int startProcess() {
final int[] pidHolder = new int[] {-1}; // because only finals can be passed to threads
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
int exitCode = startProcessBuilderwithCommand(); // starts a processbuilder with batch file
if (exitCode != 0) {
return;
} else {
pidHolder[0] = consumer.initiateConsumer(); // -> this is the process which needs to stop
}
} catch (Exception e) {
e.printStackTrace();
return;
}
}
};
return pidHolder[0];
}
Обратите внимание, что остановить поток извне еще сложнее — java-thread-stop — также нужно что-то смотреть изнутри.
Ну и где код запускающий процесс? Это не то, как работают API. Вам либо нужно, чтобы API возвращал PID, а затем вызывающий абонент может вызвать другой API, чтобы остановить его, но это звучит как проблема дизайна.