2011-02-05 2 views
2

Я пишу программу Java, включающую многопоточный пул работников Process es. Каждый экземпляр класса Process должен иметь возможность генерировать один дополнительный поток, чтобы выполнить некоторую работу. Но поток должен порождать сам экземпляр и никто другой. К сожалению, Runnable.run является «общедоступным», поэтому я не могу навязывать это без каких-либо трюков.Java: приватный вызов «run» в классе «Runnable»

Вот трюк, который я планирую использовать:

  1. Реализовать Runnable в Process
  2. Записать это в реализации:

Код:

class Process implements Runnable { 

    private boolean threadkey = false; 

    public void run() { 

     synchronized(threadkey) { 

      // is someone wrongly calling 'run'? 
      if(!threadkey) 
       return; 

      /* switch off threadkey to make sure 
      it cannot be called meaningfully again */ 
      threadkey = false; 
     } 
     /* continue processing 
     * 
     */ 
     return; 
    } 

Конечно, теперь все, что мне нужно сделать, когда я хочу run законно заключается в том, чтобы включить «threadkey» (который является приватным) перед выполнением вызова.

Элегантный? Или нет? Или есть лучший способ? Или мне просто не нужно сдерживать это и писать аккуратный небольшой комментарий, объясняющий НЕ называть «run»?

Неужели люди даже называют «run» из класса, который должен выполнять «бег»?

ответ

10

В то время как вы правильно, что run методом Runnable является общедоступным, одна вещь, которую вы можете сделать, чтобы помешать другим людям называть его, чтобы сделать весь ваш Runnable реализация пакета-частного класса или частный внутренний класс. Таким образом, хотя у него может быть метод publicrun, код, отличный от вашего пользовательского класса, не может создать объект Runnable. Если у вас также есть свой класс, не поддерживающий ссылки на него, то у клиентов не будет доступа к Runnable, и поэтому они не смогут вызывать run. То есть, у вас нет своего Process класса Runnable; вместо этого создайте другой класс, который на самом деле реализует Runnable, затем сделайте Process единственным классом, который может получить к нему доступ.

Этот подход более изящный, чем вы предлагали, поскольку он не позволяет другому коду звонить run во время компиляции, а не во время выполнения. В частности, если какой-либо код пытается вызвать ваш метод run, описанный выше, он будет компилироваться просто отлично и будет работать во время выполнения. Проблема в том, что код будет компилироваться, но может никогда работать правильно. Создание недопустимого Runnable означает, что если кто-то попытается запустить его, они получат ошибку во время компиляции и должны будут пересмотреть свой дизайн. Другими словами, компилятор обнаружит ошибку до ее возникновения.

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

6

Вы можете использовать анонимный внутренний класс Runnable так:

private void spawnThread() { 
    Thread t = new Thread(new Runnable(){ 
      public void run(){ 
      // do something 
      } 
    } 
    t.start(); 
} 

И spawnThread() можно назвать только внутри класса, так как это частная.

1

Вы не можете запустить() метод частного и использовать внутренний класс (реализации Runnable) для доступа к нему:

public class Process { 

    private Thread extraThread = null; 

    private void run() { 
     // Do you thing 
    } 

    public synchronized void spawnExtraThread() { 
    if(extraThread != null) 
     return; // Do nothing an extra thread was already spwaned 
    extraThread = new Thread() { 
     public void run() { Process.this.run(); } 
    }; 
    extraThread.start(); 
    } 
} 

Главное в том, что класс Process() больше не реализует Runnable и, следовательно, может больше не превращаются в нить. Конечно, вы расширяете эту конструкцию, чтобы поддерживать любое ограничение количества потоков (просто измените поле extraThread на массив потоков).

Смежные вопросы