powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
25 сообщений из 140, страница 5 из 6
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515534
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz,

Спасибо, да, не вовремя я подключился.
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515537
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Alexey Tomin,

Алексей Вы специально игнорируете мои сообщения? вот напрочь игнорируете - не понимаю зачем.

Я уже не раз писал, что

1. БЫЛО ОТПРАВЛЕНО ПРОСТОЕ НО МЕНЕЕ ПРОИЗВОДИТЕЛЬНОЕ РЕШЕНИЕ. С КОЛЛИЗИЯМИ. ИМ НЕ ПОНРАВИЛОСЬ ПО ПЕРФОРМАНСУ. ВСЕГО Я ОТПРАВИЛ 2!!!!! (ДВА) РЕШЕНИЯ Там код не сложнее вашего, только под все условия подходит. Второе решение реально более сложное и производлительное и пришлось почесать репу, чтобы его придумать.

А Вы будто поставили задачу оправдать этих проверяющих))

Я кстати замечу, что никто (от слова абсолютно) не предложил решения похожего по распределению задач, но более простого. Ну а к наименованию придираться можно конечно, но если тебе что-то непонятно можно спросить товарища, который это писал. Нейминг это не точная наука.

А по поводу того, что проверяющие не обязаны разбираться - ну как бы смешно. Задачу придумать они могут, простое решение не достаточно производительное, поэтому очевидно, что будет не что-то простое им отправлено и им должно хватать квалификации разбираться в том, что они задали. А так получилось, что они сами не разобрались в чем проблема. А в работе как будет? тесты упали, оооо да там всё не так, давайте всё перепишем, а там условно не хватает одного volatile
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515539
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Andrei TquestionerЕсли имелось ввиду то, что whenComplete(Async) может не выполниться, то это не правда
Наверно все-таки имелось в виду то, что надо делать так:

Код: java
1.
2.
3.
4.
5.
try {
    myTask.run();
} finally {
    countDownLatch.await();
}



Иначе возникает race condition между экзекутором и тредом, выполняющим compute, и как следствие блокировка с зависанием в отдельных случаях.

Andrei Tquestionerпропущено...

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

finally не влияет на race condition-ы
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515589
vimba
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questioner,

А у тебя бенчмарков случаем не осталось? Я чуть покрутил твой алгоритм, заменив CompletableFuture на не синхронизированную очередь(синхронизация уже провайдится compute ) и внёс(на мой взгляд) ряд оптимизиций:
Шедуля таску не надо каждые раз возвращать новый маппинг для мапы, если уже есть таска в прогрессе то просто возвращаем уже сушествующую очередь жаждущих выполнится на том же самом ключе, что позволяет не аллоцировать новый узел для мапы если уже есть таска с таким ключем в прогрессе.

Отказ от фьюч позволил совместить compute и remove в одно целое, воспользовавшись свойством того, что если compute возвращает null то entry удалается из мапы, тобишь whenCompleteAsync стал вообще не нужным, не нужно на кажду таску вкидывать в пул еще одну таску, абсолютный win на мой взгляд по CPU и аллокациям
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
private final ConcurrentHashMap<String, Queue<Task>> taskMap = new ConcurrentHashMap<>();

        public void execute(Task task) {
            taskMap.compute(task.getKey(), (key, queue) -> {
                if (queue == null) {
                    // это первая таска с ключом, создаем очередь для тех кто пожелает присоседится 
                    // пока текущая таска в прогрессе
                    queue = new LinkedList<>();
                    poolExecutor.execute(new DecoratedTask(task));
                    return queue;
                } else {
                    queue.add(task);
                    // возвращаем ту же очередь, маппинг остается нетронутым, новый узел не аллоцируюется
                    return queue;
                }
            });
        }

        private class DecoratedTask implements Runnable {
            private final Task target;

            public DecoratedTask(Task target) {
                this.target = target;
            }

            @Override
            public void run() {
                try {
                    target.run();
                } finally {
                    taskMap.compute(target.getKey(), (key, queue) -> {
                        Task nextTask = queue.poll();
                        if (nextTask == null) {
                            // ждущих тасок по этому же ключу нет просто удаляем узел из мапы
                            return null;
                        }
                        try {
                            poolExecutor.execute(new DecoratedTask(nextTask));
                        } finally {
                            return queue;
                        }
                    });
                }
            }
        }


Но надо признаться, что я этот код еще не тестил, потому что тесты дома остались, и естественно как предполагал Blazkowicz кода меньше не стало, стало только больше.
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515602
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
vimba,

я не бенчмаркил. Очень поверхностные замеры только были. тут это не поможет.

в этом решении удаление блочит бакет зато и случается абсолютно для каждой таски. А в моём варианте оно происходит параллельно с задачами из бакета и вообще не происходит в случае если фьча по этому ключу поменялась(то есть новая задача подкинулась по этому ключу).

Но на каких-то входных данных всё же видимо заработает быстрее. Думаю на реалистичных задачах он будут работать одинаково)
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515656
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vimbaкак предполагал Blazkowicz кода меньше не стало, стало только больше.
Ну, если так писать, то да. Но, что-то мне подсказывает что можно и так, например:
Код: java
1.
2.
3.
4.
5.
public void execute(Task task) {
    queueMap
        .computeIfAbsent(task.getKey(), this::scheduleNewQueue)
        .add(task);
}
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515706
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, давайте оптимизациями меряться!

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
    ConcurrentHashMap<String, Queue<Runnable>> queueMap = new ConcurrentHashMap<>();
    ExecutorService threadPool = Executors.newCachedThreadPool();

    public boolean execute(Task task) {
        return !this.threadPool.isShutdown()
                && this.queueMap
                    .computeIfAbsent(task.getKey(), this::scheduleNewQueue)
                    .add(wrapped(task));
    }

    public void stop() {
        this.threadPool.shutdown();
    }

    private Queue<Runnable> scheduleNewQueue(String key) {
        ConcurrentLinkedQueue<Runnable> queue = new ConcurrentLinkedQueue<>();
        this.threadPool.submit(() -> {
            do {
                for (Runnable task : queue) task.run();
            } while (thereAreTasks(key, queue));
        });
        return queue;
    }

    private boolean thereAreTasks(String key, ConcurrentLinkedQueue<Runnable> queue) {
        return queueMap.compute(key, (k, v) -> queue.isEmpty() ? null : queue) != null;
    }

    private Runnable wrapped(Task task) {
        return () -> {
            try {
                task.run();
            } catch (Throwable e) {
                task.fail(e);
            }
        };
    }
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515733
Andrei T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz,

Код: java
1.
2.
3.
do {
    for (Runnable task : queue) task.run();
} while (thereAreTasks(key, queue));


Рано или поздно здесь выскочит ConcurrentModificationException
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515738
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerBlazkowicz,

Это на мой взгляд самая хитрая часть этого кода и было потрачено много времени, чтобы придумать эту конструкцию

Извините, что так поздно, но мне кажется, что вы не ответили на показанный vimba спорный кусок кода
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
public class Test {

  private final static ConcurrentMap<String, CompletableFuture<Void>> taskMap = new ConcurrentHashMap<>();

  public static void main(String[] args) {

   final String key = "test1";

   System.out.println("Should be empty in map: " + taskMap.get(key));

   taskMap.compute(key, (k, queue) -> {
            System.out.println("Key " + key + " compute started");
            final CompletableFuture<Void> future=new CompletableFuture();
            System.out.println("Our future : " + future);
            //to prevent OutOfMemoryError in case if we will have too much keys
            future.whenComplete((r, e) -> {
                        System.out.println("Result in map then complete: " + taskMap.get(key));
                        System.out.println(" try to remove ...");
            		taskMap.remove(key, future);
		}
            );
            System.out.println("Lets ensure how it works if have finished already...");
            future.complete(null);
            System.out.println("Key " + key + " compute finished and removed!");
            return future;
        });
    System.out.println("Result in map: " + taskMap.get(key));
  }

}



А потом сделайте финту ушами и закомментируйте taskMap.remove(key, future);
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515744
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrei TРано или поздно здесь выскочит ConcurrentModificationException
Полюбому выскочит. Надо циклы объединить и poll использовать. Но, блин, через poll уродливо выходит.
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515745
Andrei T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrei TBlazkowicz,

Код: java
1.
2.
3.
do {
    for (Runnable task : queue) task.run();
} while (thereAreTasks(key, queue));


Рано или поздно здесь выскочит ConcurrentModificationException
Вообще-то нет, вру.
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515747
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrei T,

Путаешь меня почем зря.
javadocIterators are <i>weakly consistent</i>, returning elements
reflecting the state of the queue at some point at or since the
creation of the iterator.
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515751
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей АрсеньевИзвините, что так поздно, но мне кажется, что вы не ответили на показанный vimba спорный кусок кода
Вроде, три раза уже ответили: whenCompleteAsync()
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515753
Andrei T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczAndrei T,

Путаешь меня почем зря.
javadocIterators are <i>weakly consistent</i>, returning elements
reflecting the state of the queue at some point at or since the
creation of the iterator.
Да, ввел в заблуждение всех, сорян
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515758
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrei TДа, ввел в заблуждение всех, сорян
Но, там всё равно через poll() должно эффективнее работать.
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515770
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczВроде, три раза уже ответили: whenCompleteAsync()
Как это влияет на то, что из мапы пытаются удалить что-то до того, как туда его вставили?
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515775
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: java
1.
2.
3.
4.
5.
6.
            future.whenCompleteAsync((r, e) -> {
                        System.out.println("Result in map then complete: " + taskMap.get(key));
                        System.out.println(" try to remove ...");
            		taskMap.remove(key, future);
                        System.out.println("Result in map then remove: " + taskMap.get(key));
		}
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515776
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Result in map then remove: null
Final result in map: java.util.concurrent.CompletableFuture@3e3abc88[Completed normally]
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515778
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей АрсеньевКак это влияет на то, что из мапы пытаются удалить что-то до того, как туда его вставили?
Хороший вопрос. А ведь и правда.
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515857
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BlazkowiczСергей АрсеньевКак это влияет на то, что из мапы пытаются удалить что-то до того, как туда его вставили?
Хороший вопрос. А ведь и правда.

Это влияет на то в каком треде будет происходить удаление.

Тогда только летч поможет.
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515861
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowiczvimbaкак предполагал Blazkowicz кода меньше не стало, стало только больше.
Ну, если так писать, то да. Но, что-то мне подсказывает что можно и так, например:
Код: java
1.
2.
3.
4.
5.
public void execute(Task task) {
    queueMap
        .computeIfAbsent(task.getKey(), this::scheduleNewQueue)
        .add(task);
}



порядок мне кажется может нарушиться


1ый тред сделал computeIfAbsent
2ый тред сделал computeIfAbsent

...
2ый тред добавил в очередь
1ый тред добавил в очередь

но это мелочь
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515882
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BlazkowiczAndrei TРано или поздно здесь выскочит ConcurrentModificationException
Полюбому выскочит. Надо циклы объединить и poll использовать. Но, блин, через poll уродливо выходит.
а что с poll-ом не так?
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515904
Андрей Панфилов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczА, давайте оптимизациями меряться!
на мой взгляд стало хуже. Вот здесь задачи с одинаковым ключом получают преимущество в планировании:
Код: java
1.
2.
3.
            do {
                for (Runnable task : queue) task.run();
            } while (thereAreTasks(key, queue));


А вот здесь
Код: java
1.
  for (Runnable task : queue) task.run();


из очереди ничего удаляться не будет, for loop же не удаляет из Queue ничего, если предположить что вы забыли удалить задачу тем или иным образом (ну там poll вместо for loop), то все равно беда, потому что вот здесь:
Код: java
1.
  .add(wrapped(task));


к моменту вызова add очередь может быть уже пустой, и ничего выполняться уже не будет.
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515905
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
questionerЭто влияет на то в каком треде будет происходить удаление.
У меня это влияет и на то, вызовется потом новый whenCompleteAsync (другими словами будет ли запущен следующая задача с тем же ключом) или нет. В одном запуске теста вызывается, в другом нет. Т.е. не только утечка памяти по отработанным ключам, но и потеря задач.

Я б не мудрствовал бы и просто сделал очередь задач. И разгребальщик с мапой для работающих.

Правда ошибок бы понасажал поначалу... :)
...
Рейтинг: 0 / 0
Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
    #39515916
questioner
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей АрсеньевquestionerЭто влияет на то в каком треде будет происходить удаление.
У меня это влияет и на то, вызовется потом новый whenCompleteAsync (другими словами будет ли запущен следующая задача с тем же ключом) или нет. В одном запуске теста вызывается, в другом нет. Т.е. не только утечка памяти по отработанным ключам, но и потеря задач.



А это про какой конкретно код речь. Не очень понятно почему whenCompleteAsync может не отработать. он же цепляется к фьюче. Другое дело, что как Вы внимательно заметили в мапу значение может и не быть добавлено ещё.


Сергей АрсеньевЯ б не мудрствовал бы и просто сделал очередь задач. И разгребальщик с мапой для работающих.

Правда ошибок бы понасажал поначалу... :)

Можно как-то поподробнее?
есть очередь, есть мапа. Как они связаны? мапа очередей или очередь мап?
...
Рейтинг: 0 / 0
25 сообщений из 140, страница 5 из 6
Форумы / Java [игнор отключен] [закрыт для гостей] / Сказали, что выполнил тестовое задание неправильно, я с этим не согласен. Кто прав?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]