Вопросы по теме - java.util.concurrent - Runnable / Callable - PullRequest
0 голосов
/ 15 марта 2012

Хорошо, я собираюсь признать, что плохо знаком с потоками в Java, я много читал о java.util.concurrent, и у меня есть несколько вопросов, на которые, как я надеялся, мог ответить реальный человек.

Сначала я создал ThreadPoolExecutor и BlockQueue, чтобы помочь запустить мои методы Runnable / Callable.Для простоты с моим ограниченным знанием я ограничил все действия только для чтения, никакие Объекты, передаваемые в Runnable, не изменяются, и создаваемая информация извлекается из базы данных, которая используется приложением для заполнения таблиц GUI, любой информации вбаза данных может быть изменена либо до, либо после ее получения, не имеет значения для отображения.

Что мне интересно, так это то, что то, что я сделал, является поточно-ориентированным.Я расширил ThreadPoolExecutor, чтобы я мог переопределить метод afterExecute для выполнения метода в Runnable после того, как он завершил свою работу в потоке.Из того, что я прочитал, кажется, что эта операция выполняется в основном потоке и будет считаться поточно-безопасной.

Также продолжая эту идею, если я напишу другой метод, который также находится в этом классе Runnable / Callable, ииспользуйте его напрямую без использования run (или ThreadPoolExecutor.execute ()), чтобы он также работал в основном потоке и был безопасным.Вопрос второй: если я использую этот метод из метода run () класса Runnable, он запускается в потоке?(Я предполагаю, что это так, и запрашиваю подтверждение) И если я запустил этот метод напрямую, будет ли он выполняться в главном потоке?

Причина в том, что я хочу сохранить все, что связано с запросом /Обновление / вставка в одном классе, но сохранение обновлений базы данных в главном потоке.

Немного кода, который поможет объяснить:

Расширенный ThreadPoolExecutor:

public class DatabaseThreadPoolExecutor extends ThreadPoolExecutor {
    public DatabaseThreadPool(int corePoolSize, int maximumPoolSize, long keepAlive, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(//pass info to super)
    }

    protected void afterExecute(Runnable runnable, Throwable throwable) {
        if(runnable instanceof someRunnable) {
            ((SomeRunnable) runnable).afterExecution();
        }
    }
}

Класс Runnable:

public class someRunable implements Runable {

    public someRunnable() {
        // used code withing thread
    }

    public doAfterExecute() {
        // run by ThreadPoolExecutor .afterExecute()
    }

    public doSomething() {
        // Run by someRunnable in thread
        // Also run directly by some other class
    }
}

Какой-то другой класс, который вызывает doSomething ():

public class someOtherClass {
    public SomeOtherClass(Runnable someRunnable) {
        someRunable.doSomething();
    }
}

1 Ответ

1 голос
/ 15 марта 2012

Невозможно сказать, что такое высокоуровневое описание является «потокобезопасным», не видя весь код.Насколько мы знаем, вы используете архитектуру, в которой «чтение» является блокирующей операцией, и она может завести вас в тупик!

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

«Потокобезопасность» также не означает, что что-то действительно подходит для одновременного использования.Полностью синхронизированный ArrayList является «потокобезопасным», но вам, конечно, не захочется писать программу, которая разделяет его между множеством потоков, которые постоянно его используют!

Хотя мы постараемся ответить на ваши реальные вопросы!:

Сначала я создал ThreadPoolExecutor и BlockQueue, чтобы помочь запустить мои методы Runnable / Callable.Для простоты с моим ограниченным известным знанием я ограничил всю активность только для чтения, никакие Объекты, передаваемые в Runnable, не модифицируются

Это выглядит как явно ложное утверждение.Если ваш работоспособный объект вообще что-то делает, то материал, который вы читаете, должен куда-то идти.Это где-то должно быть что-то, на что есть ссылка. Как ресурс, который вы помещаете в результаты чтения, реагирует на одновременный доступ, - это то, что вам нужно проанализировать .Вот где кроются потенциальные опасности.

Я расширил ThreadPoolExecutor, чтобы я мог переопределить метод afterExecute для выполнения метода в Runnable после того, как он завершил свою работу в потоке.Из того, что я прочитал, кажется, что эта операция выполняется в основном потоке и будет считаться поточно-безопасной.

Нет, afterExecute () будет вызываться в том же потоке пула, который вызвал выполнение () метод на вашем работоспособном.Не в ветке, представившей Runnable." Этот метод вызывается потоком, который выполнил задачу "

Также продолжаю эту идею, если я напишу другой метод, который также находится в этом классе Runnable / Callable, и используюнепосредственно без использования run (или ThreadPoolExecutor.execute ()), который также будет работать в главном потоке и будет безопасным.

Да, он будет выполняться в потоке, в котором вы вызываете метод из, не в потоке пула.«Быть ​​безопасным» - это то, что мы не можем начать узнавать только из описания архитектуры (и согласованного определения безопасности):).

Вопрос второй: если я использую этот метод из run ()метод класса Runnable это запустить в потоке?(Я предполагаю, что это так, и запрашиваю подтверждение)

Да, все, что вы вызываете внутри метода run (), будет выполняться потоком пула, который подхватывает вашу задачу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...