Как улучшить производительность Java, используя статические переменные и потоки? - PullRequest
4 голосов
/ 18 февраля 2011

Ради того, чтобы не углубляться в то, что должно делать мое программное обеспечение, позвольте мне привести пример того, что я пытаюсь решить, чтобы сделать это коротким и приятным.

Допустим, у меня есть Базовый класс под названием X и реализация этого класса, я назову Y. Класс Y, естественно, расширяет Базовый класс X. Допустим, у меня есть 20 объектов, которые будут создавать экземпляр класса Y черезотдельный поток для каждого объекта, и при каждом создании большой файл загружается в память.Возможно, некоторым из этих объектов, возможно, понадобится использовать разные файлы, но для упрощения предположим, что им всем нужен доступ к одному и тому же файлу.

Есть ли способ определить определенный объект (переменную), который статически указывает на эти файлы в базовом классе, так что, хотя класс реализации загружается 20 раз через 20 различных потоков, они все могут совместно использоватьтот же статический объект, так что файл нужно загрузить только один раз ???

спасибо за вашу помощь заранее ...

Ответы [ 5 ]

5 голосов
/ 18 февраля 2011
  1. этот файл только для чтения?
  2. это большая строка данных?

, если так, и String, просто сделайте его protected static final String, и он безопасен для потоков. если оно изменчиво, у вас есть целый мир боли в вашем будущем.

если это двоичный файл и будет использоваться только для чтения, вы, вероятно, можете сделать то же самое с byte[] вместо String и убедиться, что вы ничего не измените в байтах в массиве. Лучшим способом было бы реализовать некоторый интерфейс Stream или Reader только для чтения.

Самый простой и безопасный способ сделать что-то потокобезопасным - сделать его неизменным. ключевое слово final делает ссылки неизменяемыми, оно не делает объект, на который он указывает, неизменным. Поскольку String является неизменным, final также делает ссылку неизменной, и вы готовы к работе. Если вам нужна изменчивость с изменениями, общими для всех потоков, пакет java.util.concurrent станет вашим другом.

Если вы сделаете переменную protected static final, то все экземпляры подкласса, независимо от того, в каком потоке выполнения они находятся, увидят данные.

1 голос
/ 18 февраля 2011

Если вы знаете файл заранее, вы можете открыть и загрузить файл в блок статического инициализатора и сохранить его содержимое в статическом элементе данных. Тогда содержимое будет доступно для всех экземпляров этого класса, независимо от того, какой поток в данный момент обращается к объектам экземпляра.

// In the base class
protected static final String fileContents;

static {
    fileContents = readStuffFromFile();
}
1 голос
/ 18 февраля 2011

Вы можете начать, используя ConcurrentHashMap .

Сделайте ключ к карте строкой, и значение должно быть таким, каким должно быть загруженное представление.если вы изменяете данные загруженного файла, вам все равно необходимо обеспечить безопасность потоков, даже если вы используете ConcurrentHashMap.

Инициализируйте эту карту перед созданием объектов и передайте ее конструктору объекта.

0 голосов
/ 18 февраля 2011

Создайте отдельный объект для хранения кэшированного содержимого файла.

Сделайте этот объект по мере необходимости потокобезопасным путем синхронизации, чтобы несколько потоков могли получить доступ к этому объекту. В вашем базовом классе X поместите ссылку на этот объект. Теперь можно создать несколько экземпляров класса X с одним и тем же кэшированным объектом. Теперь для этого требуется, чтобы этот объект загружался только один раз для каждого файла, и этот объект можно разделить между всеми необходимыми объектами X / Y.

Единственная проблема, которая остается, - это метод загрузки этих файлов. Решение этой проблемы будет зависеть от структуры вашего приложения и этих файлов, но я предложу одно из возможных решений.

Создать фабричный класс, который будет создавать объекты этого нового типа. Эта фабрика будет работать в своем собственном потоке, и все загруженные файлы будут загружены через эту фабрику. Создайте интерфейс, где файл может быть запрошен с этой фабрики. Фабрика сохраняет ссылку на все загруженные файлы, поэтому, если она уже загружена, она может сразу же вернуть ссылку. Когда он не загружен, заблокируйте поток, выполняющий вызов, используя Object.wait() для объекта-заполнителя, хранящегося на фабрике, связанной с этим файлом. Как только фабрика завершит загрузку файла, вызовите Object.notifyAll() для объекта-заполнителя для этого файла, который активирует каждый поток, и эти методы возвратятся со ссылкой на загруженный файл.

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

0 голосов
/ 18 февраля 2011

нестатический внутренний класс выполнит все ваши желания:

public class Foo {
  protected String member;
  public Foo(String member) {
    this.member = member;
  }
  public class Bar {
    protected String member;
    public Bar(String member) {
      this.member = member;
    }
    public void show() {
      System.out.println("this.member: " + this.member + "; Foo.this.member: " + Foo.this.member);
    }
  }
  public static void main(String[] args) throws javax.mail.MessagingException, java.io.IOException {
    Foo foo_a = new Foo("a");
    Foo foo_b = new Foo("b");
    Bar bar_a1 = foo_a.new Bar("1");
    Bar bar_a2 = foo_a.new Bar("2");
    Bar bar_b1 = foo_b.new Bar("1");
    Bar bar_b2 = foo_b.new Bar("2");
    bar_a1.show();
    bar_a2.show();
    bar_b1.show();
    bar_b2.show();
  }
}

Ну, хорошо, хорошо, (-2 голоса спустя):

Во-первых, ни одно из вышеперечисленных решенийобратитесь к той части исходного вопроса, что не может быть точно один файл, совместно используемый всеми объектами.Одной группе объектов может потребоваться общий доступ к файлу A, а другому файлу группы B и т. Д.Решение внутреннего класса, приведенное выше, предназначено для выполнения именно этого требования.Вы создаете экземпляр внешнего класса один раз для каждого файла / группы и создаете экземпляры внутренних объектов для группы из одного и того же внешнего объекта.

Во-вторых, статический - плохой выбор: вполне вероятно, что файл может потребоватьсяуказывается позже во время выполнения, а не при запуске программы.Приведенная выше структура внешнего / внутреннего класса решает именно эту проблему.Вы создаете экземпляр внешнего класса всякий раз, когда вам нужно.Статическая инициализация не требуется (и никаких сложных схем для отложенной статической инициализации).

В-третьих, паранойя потоков просто не была проблемой в этой проблеме (или в этом решении).Совершенно очевидно, что файл предназначен только для чтения и, следовательно, является неизменяемым, поэтому одновременное решение этой проблемы будет только отвлекать внимание от элегантных решений.

Наконец, если говорить об элегантности, то это, и, вероятно, единственныйодин.

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

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