假设我有一个扩展 Thread 的类。
所以据我目前所知:
该
run()
方法在直接调用时被视为普通方法,不会导致JVM为其创建新线程。为了使其按预期工作,
start()
必须调用该run()
方法,然后在某些 OS 暗 juju 魔术发生后调用该方法。
我的问题是:
有什么办法可以让某人超载start()/run()
并保持正常行为?
注意:您将好奇心误认为是愚蠢,无需粗鲁。
假设我有一个扩展 Thread 的类。
所以据我目前所知:
该run()
方法在直接调用时被视为普通方法,不会导致JVM为其创建新线程。
为了使其按预期工作,start()
必须调用该run()
方法,然后在某些 OS 暗 juju 魔术发生后调用该方法。
我的问题是:
有什么办法可以让某人超载start()/run()
并保持正常行为?
注意:您将好奇心误认为是愚蠢,无需粗鲁。
如果您子类化Thread
,则可以通过分别调用Thread
'sstart
或run
方法来执行此操作。但是,如果您打算将参数传递给底层代码,我建议您改为实现 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
它。顺便说一下,这是命令模式的一种实现。
当然:
class StupidThread extends Thread {
@Override
public void start() {
run();
}
}
但你为什么要这样做?您不能对 JVM 中创建的每个线程全局执行此操作,但是您可以在任何地方自由使用StupidThread
。
您可以覆盖 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();
}
}
注意:检查覆盖和重载之间的区别。这可以让你更好地理解这个问题。
如果要使用方法的重载,则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
. . .
}
}
一种替代方法是创建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 字段(其内容在对象中是不可变的)。
我发现上面给出的基于调用 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 方法。