【问题标题】:how to override thread.start() method in java?java - 如何覆盖java中的thread.start()方法?
【发布时间】:2010-10-28 06:41:12
【问题描述】:

我需要在我的 java 代码中实现 thread.start() 方法。请通过重写 thread.start() 方法的示例告诉我,它是如何工作的?

【问题讨论】:

  • 你为什么认为你需要覆盖它?
  • 请告诉我们为什么你不能在 run() 中实现你的逻辑。
  • 我有两个run()方法。我需要决定应该从具体的start()方法中调用哪个run()方法。
  • 一个 run() 方法在基类中,第二个在派生类中。
  • 在您的评论中,您说您有两种运行方法?子类中的一个?它不会弄清楚在运行时调用哪个吗?显示(示例)代码可能很有用...

标签: java multithreading


【解决方案1】:

你不应该。改写run

【讨论】:

    【解决方案2】:

    您可以像任何其他方法一样覆盖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 做了一些你几乎无法模仿的magic(本机代码)。

    如果您直接从您的start()(或任何其他方法)中调用run(),它会作为正常方法在实际线程中执行,而不是在新线程中执行。如果您不想在新线程中运行某些代码,则没有理由使用线程。

    如果确实需要,您必须将决策逻辑放入 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 的建议进行操作,会更容易理解和维护!
    这也是一个更加面向对象的解决方案...

    【讨论】:

    • 不是 start() 静态方法吗?!我该如何覆盖它
    • @shareef - 不,不是,sleep() 是静态的,但不是 start() - 至少在我使用/使用过的版本中(JDK 1.02 到 SE 8)看看在文档中:Thread.start()。也许它在某些非 SE 版本(如 android?)中是静态的,但这个问题只是被标记为纯 Java ......并且已经有将近 4 年的历史了 [:-O
    【解决方案3】:

    正如其他人所说,覆盖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() 方法被覆盖,你可以只依赖 late binding 并且会自动调用正确的方法:

    Runnable couldBeAOrB = ...;
    Thread thread = new Thread(couldBeAOrB);
    thread.start();
    

    【讨论】:

      【解决方案4】:

      您不会覆盖开始,而是覆盖“运行”。您可以通过以下方式简单地实现一个线程:

      new Thread() {
        public void run() {
          //your code here
        }
      }.start();
      //start will call the logic in your run method
      

      【讨论】:

      • 我必须在我的启动方法中调用逻辑。
      • 所以,请让我知道如何通过示例覆盖 start() 方法。
      • 在run方法中调用你的逻辑。
      • 就像我在上面的评论中所说的那样,.start() 将在你的“运行”方法中调用逻辑,所以你把你的代码放在运行方法中,我向你保证它会在什么时候被调用你打电话给 .start()。
      • 就像我上面评论的那样,我想确保调用 start() 方法中的特定 run() 方法。在我的代码中有两个 run() 方法,我想在 start 中决定() 方法,哪个 run() 将被调用。
      【解决方案5】:

      其实你可以调用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 (并行)。

      【讨论】:

      • 当然。但是如果我想要一个线程,它将以两种不同的方式运行。根据不同的条件,means 有两种不同的 run() 方法。然后我们应该使用 thread.start() 方法启动一个线程,并且我们应该有一个基于应该调用不同 run() 方法的条件。
      【解决方案6】:

      同意 Schildmeijer,不要覆盖 start,而是覆盖 run()。

      事实上,虽然 start 可以被覆盖(它不是最终的),但它会调用本机 start0 方法,这反过来会导致 VM 调用 run 方法(实际上来自本机线程/进程的上下文)。本机 start0 方法具有私有访问权限,因此即使您覆盖了 start,我也看不出您如何重现这种影响。

      调用 start() 的客户端在一个线程中(比如说,主线程),直到 run 方法完成它的工作,才会产生另一个线程。

      查看http://download.oracle.com/javase/tutorial/essential/concurrency/index.html 上有关线程的 Sun(咳咳,Oracle)教程,尤其是starting threads 部分。

      【讨论】:

      • try{ private synchronized void start() { if (threadStatus != 0) throw new IllegalThreadStateException(); group.add(this);开始0(); if (stopBeforeStart) { stop0(throwableFromStop); } this.run(); } }catch(Exception e){ System.out.println(e); } } 私有原生 void start0();
      • 在此代码中,它给出了一个错误,即启动未解决。请让我知道这段代码有什么问题。
      【解决方案7】:

      类 Worker 实现 Runnable{

      公共无效运行(){ 如果(“富”){ runFoo(); } 别的 { 运行条(); } }

      私人无效 runFoo(){ // 一些东西 }

      私有 void runBar(){ // 其他 }

      }

      我很确定,你不需要覆盖 start-Method。

      顺便说一句:看看 java.util.concurrent.Callable

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

      【讨论】:

        【解决方案8】:

        不鼓励重写 Thread,如果可能的话,创建一个 Runnable 接口的实现并在线程上运行它。这也可以使用 lambda 表达式来完成,让一切都变得非常简短。

        // create a new thread and give it a Runnable with a lambda expression and a custom name
        Thread thread = new Thread(() -> {
            // put your code here
        }, "CustomThreadName");
        
        // start it
        thread.start();
        

        【讨论】:

          【解决方案9】:

          如果我们提供自己的 start 方法实现,那么它将像普通的方法调用一样工作,并且只在当前线程堆栈上工作。不会创建新线程。

          【讨论】:

            【解决方案10】:

            是的,start() 方法可以被覆盖。
            但它不应该被覆盖,因为它在线程类中的实现具有创建新的可执行线程的代码并且是专门的。

            【讨论】:

              【解决方案11】:

              我们可以重写 Thread 类的 start/run 方法,因为它不是 final 的。但不建议重写 start() 方法

              class Bishal extends Thread { 
              public void start() 
                  { 
                      System.out.println("Start Method"); 
                  } 
              public void run() 
                  { 
                      System.out.println("Run Method"); 
                  } 
              } class Main{ 
              public static void main(String[] args) 
                  { 
                      Bishal thread = new Bishal(); 
                      thread.start(); 
                      System.out.println("Main Method"); 
                  } 
              } 
              

              当我们通过 Bishal 类的对象调用 start() 方法时,不会创建任何线程,所有功能都由主线程完成。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2015-08-18
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多