Как переопределить метод thread.start () в Java? - PullRequest
5 голосов
/ 28 октября 2010

Мне нужно реализовать метод thread.start () в моем коде Java.Пожалуйста, дайте мне знать через пример переопределения метода thread.start () и как он работает?

Ответы [ 9 ]

14 голосов
/ 28 октября 2010

Вы не должны. Переопределить запустить вместо

12 голосов
/ 28 октября 2010

Как говорили другие, переопределение Thread.start() не способ сделать это.Обычно я бы тоже не переопределил Thread.run(), но использовал бы Runnable.

Если вам нужно решить, какой метод запустить после порождения потока, вы можете сделать что-то вроде этого:

final Runnable runnableA = ...;
final Runnable runnableB = ...;

Runnable r = new Runnable() {
    @Override
    public void run() {
        if (...) {
            runnableA.run();
        } else {
            runnableB.run();
        }
    }
}

Thread thread = new Thread(r);
thread.start();

Если, как вы говорите, у вас есть суперкласс и подкласс, где метод run() переопределяется, вы можете просто положиться на позднее связывание и правильный метод будет вызван автоматически:

Runnable couldBeAOrB = ...;
Thread thread = new Thread(couldBeAOrB);
thread.start();
11 голосов
/ 28 октября 2010

Вы можете переопределить start, как и любой другой метод

    Thread myThread = new Thread() {

        @Override
        public void start() {
            // do something in the actual (old) thread
            super.start();
        }

        @Override
        public void run() {
            // do something in a new thread if 'called' by super.start()
        }
    };

но вы должны вызвать super.start(), чтобы создать новый поток, и run() вызвать в этом новом потоке. Оригинальный start обладает магией (нативный код), которую вы вряд ли сможете имитировать.

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

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

    class MyThread extends Thread {

        private final boolean flag;

        public MyThread(boolean someCondition) {
            flag = someCondition;
        }

    // alternative  
    //    @Override
    //    public synchronized void start() {
    //        flag = <<someCondition>>
    //        super.start();
    //    }

        @Override
        public void run() {
            if (flag) {
                // do something like super.run()
            } else {
                // do something else
            }
        }
    }

но было бы легче понять и поддерживать, если бы вы делали это так, как предложил @Henning!
Это также более объектно-ориентированное решение ...

4 голосов
/ 28 октября 2010

Вы не переопределяете начало, вы переопределяете «запуск».Вы можете просто реализовать поток с помощью:

new Thread() {
  public void run() {
    //your code here
  }
}.start();
//start will call the logic in your run method
3 голосов
/ 28 октября 2010

На самом деле, вы можете вызвать run () для запуска потока вместо start () для запуска потока. Но есть небольшая разница.

Предположим, вы создали две темы:

Thread t1 = new Thread();
Thread t2 = new Thread();

Случай 1: Если вы вызываете "t1.run ()" и "t2.run ()" один за другим, они начинают синхронно запускать t1 и t2 ( последовательно ).

Случай 2 : если вы вызываете "t1.start ()" и "t2.start ()" один за другим, они будут вызывать свои методы run () и запускать асинхронный запуск t1 и t2 ( параллельно ).

2 голосов
/ 28 октября 2010

класс Worker реализует Runnable {

public void run () {if ("foo") {runFoo ();} else {runBar ();}}

private void runFoo () {// что-то}

private void runBar () {// else}

}

Я почти уверен, что вам не нужно перезаписывать метод запуска.

Кстати: посмотрите на java.util.concurrent.Callable

http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Callable.html

2 голосов
/ 28 октября 2010

Согласитесь со Schildmeijer, не переопределяйте start, вместо этого переопределяйте run ().

Фактически, хотя start может быть переопределен (он не является окончательным), он вызывает собственный метод start0, который, в свою очередь, заставляет виртуальную машину вызывать метод run (фактически из контекста собственного потока / процесса). У нативного метода start0 есть закрытый доступ, поэтому даже если вы отвергли начало, я не вижу, как вы можете воспроизвести эффект.

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

Взгляните на учебник Sun (ahem, Oracle) по потокам по http://download.oracle.com/javase/tutorial/essential/concurrency/index.html,, в частности, по начальным потокам .

0 голосов
/ 09 сентября 2014

Да, метод start () может быть переопределен.
Но это не должно быть переопределено, поскольку реализация в классе потока имеет код для создания нового исполняемого потока и является специализированной.

0 голосов
/ 22 сентября 2013

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

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