重载Thread.start()

时间:2012-09-27 08:22:32

标签: java multithreading

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

据我所知,到目前为止:

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

  • 为了让它按预期工作,必须调用start()方法,然后调用run()方法,在一些操作系统暗淡的juju魔法发生之后。< / p>

我的问题是:

是否有人可以重载start()/run()并保持正常行为?

注意:你错误的好奇心是愚蠢,不需要粗鲁。

6 个答案:

答案 0 :(得分:5)

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

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 } } a是此示例中的一些“参数。您可以将实例传递到constructor中的b,然后只传递Thread顺便说一句,这是Command Pattern的实现。

答案 1 :(得分:3)

当然:

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

但你为什么要这样做?对于在JVM中创建的每个线程,您无法为全局执行此操作,但您可以随时随地使用StupidThread

答案 2 :(得分:3)

您可以覆盖Thread中的start / run方法,因为Thread类中的start和run方法不是final方法。 例如: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();
    }   
}

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

答案 3 :(得分:2)

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

至于重载start()方法。它可以被认为是一种调用pthread_create()或类似的JNI方法,然后调用您的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
          . . .
     }
 }

答案 4 :(得分:2)

另一种方法是创建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字段(如果对象的内容是不可变的)。

答案 5 :(得分:0)

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

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方法。