假设我有一个扩展Thread的类。
据我所知,到目前为止:
run()
方法在直接调用时被视为普通方法,并且不会导致JVM为其创建新线程。
为了让它按预期工作,必须调用start()
方法,然后调用run()
方法,在一些操作系统暗淡的juju魔法发生之后。< / p>
我的问题是:
是否有人可以重载start()/run()
并保持正常行为?
注意:你错误的好奇心是愚蠢,不需要粗鲁。
答案 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方法。