1

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

所以据我目前所知:

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

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

我的问题是:

有什么办法可以让某人超载start()/run()并保持正常行为?

注意:您将好奇心误认为是愚蠢,无需粗鲁。

4

6 回答 6

5

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

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并且b是此示例中的“参数”。您可以将实例传递给 aThread在其构造函数中,然后将其传递给start它。顺便说一下,这是命令模式的一种实现。

于 2012-09-27T08:30:20.940 回答
3

当然:

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

但你为什么要这样做?您不能对 JVM 中创建的每个线程全局执行此操作,但是您可以在任何地方自由使用StupidThread

于 2012-09-27T08:25:27.193 回答
3

您可以覆盖 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();
    }   
}

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

于 2012-09-27T09:33:27.670 回答
2

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

至于重载start()方法。可以将其视为调用pthread_create()或类似方法然后调用您的方法的 JNIrun()方法。实际上,出于性能原因,它可能以不同的方式实现。你最好不要插手。但是,您可以考虑重载线程构造函数,如本页第一个示例所示: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
          . . .
     }
 }
于 2012-09-27T08:32:49.377 回答
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 字段(其内容在对象中是不可变的)。

于 2012-09-27T09:05:44.200 回答
0

我发现上面给出的基于调用 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 方法。

于 2017-01-04T11:02:20.757 回答