Страницы

Поиск по вопросам

суббота, 30 марта 2019 г.

Можно ли средствами Java убить дочерние процессы процесса, созданного с помощью ProcessBuilder?

Если создать процесс
ProcessBuilder builder = new ProcessBuilder("command"); final Process process = builder.start();
то его можно будет убить с помощью: process.destroy();
Но что, если этот command наплодит кучу других процессов? process.destroy(); уже будет не в силах убить их. И они останутся в памяти.
При этом, если из командной строки сделать Ctrl+C, то дочерние процессы тоже завершатся.
В сети много вопросов на эту тему (большинство из них старые) и почти все ответы говорят о том, что это невозможно сделать средствами JVM - нужно обращаться к ОС. Решил задать вопрос, в надежде на то, что это всё же стало возможным с появлением Java 8. Хочется получить решение, не зависимое от ОС.
Возможно ли на сегодняшний день средствами Java убить дочерние процессы процесса, созданного с помощью ProcessBuilder, не манипулируя напрямую с командами ОС? Если возможно, то как это реализовать? Если нет, то ожидается ли такая возможность в Java 9?
UPDATE
Хочу ещё раз выделить то, что я не ищу решения, зависящие от ОС. По этой ссылке можно прочитать о том, как искать PID процесса в Unix и Windows. Потом можно будет обратиться к терминалу с соответствующей командой для "убийства" процесса.
Это не является темой данного вопроса.


Ответ

В версиях Java до 8й включительно инструментарий для работы с процессами был довольно скудным.
Но если ознакомиться, с JEP 102: Process API Updates (который реализуется в рамках Java 9), то мы увидим, что Brian Goetz говорит нам о следующих вещах:
Возможность получить pid процесса JVM и pid-ы процессов, запущенных средствами API. Возможность получить список запущенных в системе процессов, включая их pid, состояние, наименование и, возможно, потребление ресурсов. Возможность взаимодействовать с деревьями процессов, а именно прекращать работу целого дерева. Возможность взаимодействовать с сотнями дочерних процессов, возможно, мультиплексируя потоки вывода и ошибок, чтобы избежать создания отдельной нити (thread) на каждый процесс.
Все эти радости уже можно потрогать в 9ке: см. интерфейс ProcessHandle
long getPid() static Stream allProcesses() и ProcessHandle.Info info() Stream descendants()

Как преобразовать double? в double на C#

Есть поле класса типа double?, то есть оно может и не содержать значения.
А я в своем классе использую просто double
Как сделать преобразование?
И как быть с DateTime? -> DateTime


Ответ

Если вы уверены, что значение там есть, вы можете получить его так:
double? nd = ...; double v = nd.Value;
Если не уверены, вам придётся сначала проверить:
double? nd = ...; if (nd == null) { // значения нет, обрабатываем этот случай } else { // значение есть double d = nd.Value; // работаем с ним }
Для случая, когда для отсутствующего значения подойдёт, например, 0.0, можно написать просто так:
double d = nd ?? 0.0;
Но как именно правильно реагировать на отсутствующее значение, решать только вам.

Чем канонические геттеры и сеттеры лучше открытого поля?

Не понимаю, в чем плюс использования канонических (только возвращающих и устанавливающих занчение) геттеров и сеттеров перед открытым полем? Чем вот такой код:
private MyJDesktopPane desktop;
public MyJDesktopPane getDesktop() { return desktop; }
public void setDesktop(MyJDesktopPane desktop) { this.desktop = desktop; }
Лучше такого:
public MyJDesktopPane desktop;
Понимаю, если в сеттере например используются какие-либо проверки на корректность введенного значения или идет согласование введенного значения с другими полями класса.
Скажу честно, до проблемы додумался не сам, прочитал о ней в статье "10 приемов, разрушающих хрупкую красоту кода" на Хабре.


Ответ

Это "запас на будущее".
Сейчас вам достаточно поля, так как у вас публичны и чтение, и запись, а никакой дополнительной логики нет. Теперь допустим, что вам понадобилась эта логика. Что вы будете делать? Вы скроете поле, напишете геттеры и сеттеры. И тут возникает проблема: надо переписать все доступы к полю во всех классах, работающих с вашим кодом; надо перекомпилировать весь код, который обращается к полю. Часто это может быть большой объём работы, и он может повлечь за собой тьму тьмущую неприятностей, особенно если одновременно поддерживается несколько версий приложения: привет конфликтам мержа кода и прочим радостям.
Всё потому, что изменение поля на геттеры и сеттеры — это изменение, ломающее обратную совместимость, а добавление логики в геттер или сеттер — совершенно безболезненное изменение реализации. При хорошей архитектуре изменение реализации не должно влиять на внешний интерфейс и не должно ломать обратную совместимость. Поэтому предпочтение отдаётся геттерам и сеттерам даже тогда, когда реальной нужды в них нет.
Лирическое отступление: в C# синтаксис доступа к публичным полям и к публичным свойствам (парам геттер+сеттер) идентичен. Однако даже в C# считается дурным тоном использование публичных полей. Во-первых, потому что ломается бинарная совместимость, несмотря на сохранение совместимости на уровне сорцов; во-вторых, потому что публичные поля могут быть переданы по ссылке (ref, out), что невозможно для свойств.

Прочитал статью. Надо заметить, что рекомендация воздерживаться от геттеров и сеттеров в статье универсальна и оторвана от конкретных языков. Нельзя реализовать все рекомендации из статьи, если оставаться в рамках синтаксически аскетичного языка. Вы не можете воспользоваться синтаксическии сахаром в виде свойств, которые выразительнее, чем геттеры и сеттеры, если язык эти свойства не поддерживает. В этом случае придётся использовать геттеры и сеттеры, а не публичные поля, впрочем. Ну или переходите на C#. :)

задача: возможно ли продолжить фрагмент в обе стороны?

Задача из области "алгоритмы и структуры данных".
Дан фрагмент последовательности скобок, состоящей из символов
(){}[]
Требуется определить, возможно ли продолжить фрагмент в обе стороны, получив корректную последовательность. Если возможно - выведите минимальную корректную последовательность, иначе - напечатайте "IMPOSSIBLE". Максимальная длина строки 10^6 символов.
Sample Input 1:
}[[([{[]}
Sample Output 1:
{}[[([{[]}])]]
Sample Input 2:
{][[[[{}[]
IMPOSSIBLE
Идеи:
Есть стандартный алгоритм проверки корректности расстановки скобок, реализуемый через стэк. Суть в следудующем:
идем по строке, если встречаем открывающую скобку - заносим в стек если встречаем закрывающую скобку и на вершине стека лежит аналогичная ей открывающая, то удаляем ее (открывающюю) из стека если после прохода всей строки стек пустой, значит скобки расставлены верно.
Для решения этого задания этот алгоритм нужно модифицировать, чтобы была возможность (или определить невозможность) дополнения проверяемой строки до корректной.
Для этого пытался заводить счетчики на каждую скобку и ее направление и держать противоположную скобку в деке и в нужный момент извлекать из дека. Но пока все покрывается ифами и алгоритм все равно правильно не работает


Ответ

Привет со Степика! Держи код, прошедший все тесты в том уроке: Pastebin
В кратце об алгоритме:
открывающие скобки заносим в стек встречая закрывающие скобки проверяем на соответствие последней в стеке соответствует -> убираем из стека, иначе -> см.пункт 3 стек пуст? -> выводим слева, иначе -> IMPOSIBLE если после полного прохода последовательности стек не пуст, дополняем справа
class Stack: def __init__(self): self.items = [] def isEmpty(self): return self.items == [] def push(self, item): self.items.append(item) def pop(self): return self.items.pop() posible = True cin = input() a=Stack() s=Stack() for i in cin: if ( i == '(' or i == '[' or i == '{' ): s.push( i )
if ( i == ')' or i == ']' or i == '}'): if s.isEmpty(): a.push(i) else: temp = s.pop() if (i == ')' and temp != '(') or (i == ']' and temp != '[') or (i == '}' and temp != '{'): posible = False break if posible: while not a.isEmpty(): temp = a.pop() if temp == ']': temp = '[' if temp == ')': temp = '(' if temp == '}': temp = '{' print(temp, end = '') print(cin, end = '') while not s.isEmpty(): temp = s.pop() if temp == '[': temp = ']' if temp == '(': temp = ')' if temp == '{': temp = '}' print(temp, end = '') else: print('IMPOSSIBLE')

Как сделать, чтоб LinearLayout выделял всем item одинаковое по размеру место?

Я с помощью BaseAdapter устанавливаю в ListView XML файл со своей разметкой. В ListView в каждой строчке должно быть 3 столбца каждый из которых должен занимать 33% по ширине. Не больше ни меньше!
**Вот я собираю такой XML : **




Но все равно когда я устанавливаю в первое TextView текст, то он растягивается на где то на 70% по горизонтали, а остальные 2 TextView разделяют между собой остальных 30%. Я рассчитывал что каждый item займет третью часть по горизонтали. Что я делаю не так?


Ответ




Переопределение ссылок

В учебнике написано, что любая ссылка должна быть определена в момент объявления, и определена объектом, а не литералом. И её нельзя перевязать на другой объект. Из любопытства сделал следующее:
{ int val = 20,val2 = 2; int &refVal = val; refVal = val2; cout< return EXIT_SUCCESS; }
И к моему удивлению, на выходе ссылка ссылается на переменную val2, в консоли выводит двойку. Как так, это от компилятора зависит? Либо автор не прав. Можно ссылку на официальную документацию? Это вообще нормально?


Ответ

Дело в том, что ссылка это просто синтаксический сахар над указателями, поэтому, если переписать Ваш код через них, должно быть понятно, что происходит:
{ int val = 20,val2 = 2; int*const refVal = &val; *refVal = val2; cout<<*refVal< return EXIT_SUCCESS; }
Заметьте, в коде выше мы лишь единожды инициализируем указатель, а потом уже всюду его разыменовываем, не меняя его, но меняя тот объект, на который он указывает. Так вот, ссылка, будучи инициализирована, не может быть изменена, это просто синтаксически невозможно. Любое последующее использование ссылки является обращением к тому объекту, на который она ссылается(разыменование указателя в моём примеру).

Как изменить цвет в ActionBar?

Как можно поменять цвет в ActionBar (android), например на синий?


Ответ

В файле style.xml пишем следующее

Ну а в минифесте прописываем нашу тему, например для всего приложения
Ну и в файле colors.xml добавляем цвет
#669f36 #ffffff

Понимание Android adapters

Только сделал старт в изучении android. В общих чертах понимаю что adapter - это что-то, промежуточное между моделью и представлением.
Но помогите лучше понять, что это такое и все его возможности и применения.
П.С. если можно какие-то ресурсы или материалы.


Ответ

Начнем с того, что Adapter это не какой то неведомый абстрактный класс, а один из основных структурных шаблонов проектирования, который описан и разобран максимально подробно.
в общем случае, назначение адаптера - преобразовать один вид информации в другой, без вмешательства в исходное состояние информации.
Известно, что в ООП всё - объект, парадигма объектно-ориентированного программирования подразумевает, что виртуальная программа устроена так же, как и все, что окружает нас в реальной жизни, поэтому наглядным живым примером адаптера будет, как это ни странно - адаптер, приспособление для соединения не соединяемого, например, переходник SVGA - HDMI для подключения старой видеокарты к новому монитору.
Конкретно в Android паттерн Adapter нашел одно из своих применений в формировании различных списков на экране по имеющимся данным. То есть, есть какая то структура упорядоченных данных и ее необходимо отобразить на экране устройства. Структура представляет собой какие то цифры, текст и тому подобное, на экране это все должно быть View - явная несовместимость между источником и приемником. Можно решить эту проблему разными способами, например, предварительно преобразовать данные в подходящее для вывода на экран представление, НО! так мы потеряем исходные данные и при каждом изменении данных потребуется новое преобразование, что выглядит очень сомнительно с точки зрения производительности.
Здесь на помощь и приходит адаптер, который стоит посредником между данными и экраном, преобразуя "на лету" данные в View, не изменяя первые.
Адаптер ПОСЛЕДОВАТЕЛЬНО берет единицу данных, соответствующюю текущей ЗАТРЕБОВАННОЙ виджетом ПОЗИЦИИ одного из айтемов списка и преобразует эту единицу данных в форму, пригодную для отображения на экране - генерирует View. Виджет, отдав адаптеру требуемую позицию, в ответ получает от адаптера визуальное представление, состоящее из помещенных в нем данных и выводит его на экран.
Все возможности и применения адаптеров исходят из вышеизложенного - адаптация одного вида данных к другому. Применение адаптеров, связанных с виджетами, вроде ListView, ограничено преобразованием структурированных данных в отображение на экране, но ничто вам не мешает использовать сам паттерн для решения любых аналогичных преобразований и здесь его применение ограничено только вашей фантазией.

третий параметр алгоритма find

Используя метод find, легко найти есть ли заданное значение в контейнере, или нет:
std::vector vec; std::vector::iterator itr = find(vec.begin() ,vec.end(), int val); if(...)
и так далее;
Но что, если вектор содержит какие-либо структуры, объекты, или даже указатели на них? Возможно ли использовать эту функцию для нахождения необходимого значения, если оно является полем класса, а вектор состоит из указателей на объект этого класса? Что-то вроде:
class ClassName { public: int x; std::string y; };
std::string foo = "bar"; std::vector vec1; std::vector::iterator itr = find( vec1.begin(), vec1.end(), ??? )
Что нужно написать вместо знаков вопроса, чтобы найти такой указатель, который указывает на объект, поле std::string y которого равно строке foo ? Если это невозможно с алгоритмом find, то какие альтернативы?


Ответ

Используйте find_if, она принимает предикат.
std::string foo = "bar"; std::vector vec1; auto itr = std::find_if(begin(vec1), end(vec1), [&](ClassName* el){ return el->y == foo; });

Контроллировать I/O другой программы на C/C++

Здравствуйте. Возможно тема немного сбивает с толку, по этому поясню проще: мне нужна программа на С/С++, которая сможет запустить переданную ей в аргументы другую программу, а потом дать ей кое-что на вход (input), подождать пока она (переданная ей программа) сделает свое и получить её вывод (output). И ещё: программа, которую я передам в аргументы моей программе-оболочке -- скрипт на Python 3, может это важная деталь. Программа будет под Linux. Собственно мне нужно узнать через какие функции можно это сделать (я имею ввиду делать ввод в программу и получать её вывод).


Ответ

Посмотрите в сторону popen - например, здесь или здесь - это вам не поможет?