【问题标题】:Overloading Thread.start()重载 Thread.start()
【发布时间】:2012-09-18 23:30:57
【问题描述】:

假设我有一个扩展 Thread 的类。

据我目前所知:

  • run()方法在直接调用时被当作普通方法处理,不会导致JVM为其创建新线程。

  • 为了使其按预期工作,必须调用start() 方法,然后在某些操作系统暗juju 魔法发生后调用run() 方法。

我的问题是:

有什么方法可以让start()/run() 过载并保持正常行为?

注意:你把好奇心误认为是愚蠢,没必要粗鲁。

【问题讨论】:

  • 你的意思是 override重载你想做什么?
  • @Thilo 重写 Thread 的 run 方法是完全正常的。
  • @dystroy:我不这么认为。它已接近弃用。 stackoverflow.com/questions/2782744/…
  • @Thilo Deprecated 在这里有点强。也许不是首选...
  • @Ameoo 你应该试着解释你的目标是什么。因为没有人知道你重写 start 的原因是什么。

标签: java multithreading


【解决方案1】:

如果您子类化Thread,则可以通过分别调用Threadstartrun 方法来执行此操作。但是,如果您打算将参数传递给底层代码,我建议您改为实现 Runnable 并将参数保持在其状态:

class MyRunnable implements Runnable {

    private final int a;
    private final int b;

    public MyRunnable(int a, int b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public void run() {
        // do something with a and b
    }   
}

ab 是此示例中的“参数”。您可以将实例传递给 Thread 在其 constructor 中,然后只需 start 它。顺便说一句,这有点像Command Pattern 的实现。

【讨论】:

  • +1。也让你更灵活,因为你根本不必使用 Thread,你可以使用 Executors。
【解决方案2】:

您可以覆盖 Thread 中的启动/运行方法,因为 Thread 类中的启动和运行方法不是最终方法。 例如:isAlive()、stop()、suspend()、join() 是最终方法。所以你不能覆盖。

public class TempThread extends Thread
{
    @Override
    public synchronized void start() {
        // TODO Auto-generated method stub
        super.start();
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
    }       

    public static void main(String[] args) 
    {
        TempThread t = new TempThread();
        t.start();
        t.run();
    }
}

但正如你所问的过载

您可以重载这些方法中的任何一个。

例如:

public class TempThread extends Thread
{
    @Override
    public synchronized void start() {
        // TODO Auto-generated method stub
        super.start();
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
    }

    // ******** Overload **********
    public synchronized void start(int i) {
        // TODO Auto-generated method stub
        super.start();
    }

    // ********* Overload **********
    public void run(int i) {
        // TODO Auto-generated method stub
        super.run();
    }

    public static void main(String[] args) 
    {
        TempThread t = new TempThread();
        t.start();
        t.run();
    }   
}

注意:检查覆盖和重载之间的区别。这可以让您更好地了解该问题。

【讨论】:

  • 我知道区别,我问的是重载,而不是覆盖。您提供的答案是回答我的问题,因为我可以调用类似 start(parameter),然后在 super.start() 之前,我可以设置参数。谢谢。
  • @Munesh t.run() 将成为TempThreadMainThread 的一部分?表示哪个线程将执行t.run()
  • @UnKnown : t.run() 将执行 TempThread 的 run() 方法。 t.start() 将执行 TempThread。当我们运行 Java 程序时,它会自动启动主线程,并且您调用的任何线程(t.start())都将从主线程调用。
【解决方案3】:

当然:

class StupidThread extends Thread {
    @Override
    public void start() {
        run();
    }
}

但是你为什么要这样做呢?您不能对 JVM 中创建的每个线程全局执行此操作,但是您可以随意使用 StupidThread

【讨论】:

  • This is StupidThread 实际上是 sudo 线程。你不能打断它。
  • +1 这是唯一真正回答问题的答案。
【解决方案4】:

如果您想使用run() 方法的重载,您必须从run() 方法的主体中执行此操作。当然如果你这样做,你最好不要调用方法run()

至于重载start() 方法。它可以被认为是一个 JNI 方法,它调用 pthread_create() 或类似的方法,然后调用你的 run() 方法。实际上,出于性能原因,它可能以不同的方式实现。你最好不要插手。但是,您可以考虑重载线程构造函数,如本页第一个示例所示:http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html

 class PrimeThread extends Thread {
     long minPrime;
     PrimeThread(long minPrime) {
         this.minPrime = minPrime;
     }

     public void run() {
         // compute primes larger than minPrime
          . . .
     }
 }

【讨论】:

    【解决方案5】:

    另一种方法是创建Runnable 的匿名实例。这将允许您访问最终局部变量和最终参数(创建Runnable 的方法)以及创建Runnable 的类的字段。此外,您还可以访问封闭类的方法。

    例如。

    class SomeClass {
    
        // constructor, getter and setter not included for brevity
    
        private String field;
    
        public void startNewThread(final String parameter) {
            final double local = Math.random();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(field + parameter + local);
                }
            }).start();
        }
    }
    

    警告:由于封闭类可能被另一个线程修改,因此不鼓励直接访问非最终字段,因为您会获取过期值。要么通过同步的 getter 进行访问,要么只访问 final 字段(其内容是不可变的 if 对象)。

    【讨论】:

      【解决方案6】:

      我发现上面给出的基于调用 super.start() 的方法没有按预期并行化。一种解决方法是将参数作为成员变量传递给线程的子类:

      public class MyRunnable extends Thread {
          private int id=0;
          MyRunnable(int i){
          this.id=i;
      }
      
      
      public void run() {
          System.out.println("Starting run: " + (id+1));
          try {
              TimeUnit.SECONDS.sleep(5);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
          System.out.println("Finishing run: " + (id+1));
      }
      
      public static void main(String args[]) {
          MyRunnable threadArray[] = new MyRunnable[5];
          for (int j = 0; j < 5; j++) {
              threadArray[j] = new MyRunnable(j);
              threadArray[j].start();
          }
      }
      
      
      }
      

      显然我在这里使用了构造函数,但您可以在调用 run() 方法之前使用 setter 方法。

      【讨论】:

        猜你喜欢
        • 2011-09-05
        • 2014-05-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-31
        • 2013-12-20
        相关资源
        最近更新 更多