Вопрос по свойствам jvm и многопоточности - PullRequest
1 голос
/ 15 мая 2011


Мне нужно использовать (на данный момент) некоторые Java-API, которые -unfortunatelly- можно «настроить» только через свойства jvm.
Я понимаю, что это может повлиять на многопоточность, поскольку может быть так, что один поток, изменяющий свойства, может влиять на другие работающие.
Поэтому я подумал сделать это внутри синхронизированного метода, например

public static sychronized void someMethod(){
   Security.setProperty("responderURL",IP);
   //do code here
}

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

Спасибо

Ответы [ 4 ]

4 голосов
/ 15 мая 2011

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

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

2 голосов
/ 15 мая 2011

Синхронизация не требуется, System.setProperty - это уже синхронизированный метод, и хотя System.getProperty не синхронизирован, класс Properties расширяет HashTable, который имеет синхронизированный метод, для доступа к его парам ключ-значение. В результате вам не нужно беспокоиться о проблемах синхронизации ..

РЕДАКТИРОВАТЬ:

Некоторые разъяснения по поводу моего ответа;

1. Если ваш метод должен работать как элементарная единица, он должен быть синхронизирован, например;

    public static sychronized void someMethod(){
       if (System.getProperty("responderURL")==null)
           System.setProperty("responderURL",IP);
       //do code here
       //some code
       URL url  = new URL(System.getProperty("responderURL"),8080,"test.txt");
    }

Вы должны синхронизировать свой метод, потому что, пока Поток 1 проверяет свойство responsederURL, Поток 2 может установить это свойство.

2.Но если ваш метод устанавливает только свойство responsederURL и его функциональные возможности не зависят от текущего значения свойства responserURL, вам не нужно синхронизировать ваш метод ..

  public static  void someMethod(){
            System.setProperty("responderURL",IP);
           //do code here
           //some code
           URL url  = new URL(IP,8080,"test.txt");
      }
0 голосов
/ 01 июня 2011

Если это однократная конфигурация, вы делаете это в блоке статической инициализации. Если нет, то у вас есть классическая проблема читателя-писателя. У java.util.concurrent javadocs есть несколько хороших примеров решений.

0 голосов
/ 15 мая 2011

Использование синхронизированного вам здесь не поможет.В вашем примере synchronized делает только то, что два потока не могут одновременно вызывать ваш синхронизированный метод .

public class Foo {
  public static synchronized void bar() {
       //...    
  }
}

точно так же, как

public class Foo {
  public static void bar() {
      synchronized (Foo.class) {
       //...    
      }
  }
}

т. е. только код, который может видеть Foo.class и синхронизировать его, будет зависеть от вашей синхронизации.Поскольку код в любых библиотеках, которые вы вызываете, явно не знает о Foo.class, синхронизация с ним не будет иметь никакого эффекта.

Если вы хотите гарантировать , что эти системные свойства установлены ранеелюбой код, который может прочитать значения, может быть запущен, самый пуленепробиваемый способ - передать их в качестве аргументов -D команде java, которая запускает JVM, например, java -DresponderURL=http://foo.bar.

Следующий лучший подход -как вы делаете, установите свойства в некотором методе, называемом в начале запуска VM .Всегда желательно делать это с аргументами командной строки, если это возможно, по этой причине: если какие-либо такие свойства читаются в статических блоках {} в библиотеках, которые вы используете, эти блоки могут выполнятьсядо того, как ваш код сделает, потому что верификатор байт-кода Java может вызвать инициализацию этих классов до того, как ваш код сделает что-либо, что вызывает их (вы можете избежать этого, передав -Xverify:none команде Java, но если вы можете сделать это, вы также можетевсе равно просто установите там системные свойства).

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