对于我的论文,我正在研究一个离散事件系统模拟器。模拟包含一组SimulatorThread extends Thread
,其行动包括将Event
安排到Simulator
。每个SimulatorThread
都会与Simulator
到SimulatorInterface
进行交互。
public abstract class SimulatorThread extends Thread {
private SimulatorInterface si;
public SimulatorThread(SimulatorInterface si) {
this.si = si;
}
...
}
public final class Simulator {
private ExecutorService exec;
...
public void assignThread(SimulatorThread... stList) {
...
}
}
在模拟开始之前,每个SimulatorThread
都分配给Simulator
,然后Simulator
将通过exec.execute(simulatorThread)
执行每个线程。我的问题是在代码的某些部分我需要获得对当前运行SimulatorThread
的引用,但是指令(SimulatorThread) Thread.currentThread()
给出了一个强制执行。事实上System.out.print(Thread.currentThread().getClass())
的输出是class java.lang.Thread
,但我希望输出是class SimulatorThread
,可以通过使用指令simulatorThread.start()
运行线程而不是使用执行程序来获得。所以我认为问题在于编写一个返回ThreadFactory
实例的 ad-hoc SimulatorThread
。
事实上我试图使用琐碎的SimulatorThreadFactory extends ThreadFactory
:
public class SimulatorThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
return new SimulatorThread(new SimulatorInterface());
}
}
并且通过这个我获得了之前引用的输出'class SimulatorThread'。问题是,当我调用'exec.execute(simulatorThread)'时,参数有一个属性'SimulatorInterface',我需要访问它,但我不能因为'newThread'方法的参数是'Runnable' ”。我在这里暴露了一个错误的代码,我希望表达的意思比我用文字解释的更好:
public class SimulatorThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
SimulatorInterface si = r.getSimulatorInterface(); // this is what
// I would like
// the thread factory
// to do
return new SimulatorThread(si);
}
}
那么,如何在方法newThread
内访问'SimulatorThread'的属性'SimulatorInterface',以便在SimulatorThread
的参数为Runnable
的情况下创建{{1}}?
答案 0 :(得分:3)
如果我了解您的需求,正确的方法是不扩展Thread
,而是实施Runnable
。然后,您可以享受您自己的类层次结构的所有好处:
public abstract class SimulatorRunnable extends Runnable {
protected SimulatorInterface si;
public SimulatorRunnable(SimulatorInterface si) {
this.si = si;
}
}
public final class Simulator extends SimulatorRunnable {
public Simulator(SimulatorInterface si) {
super(si);
}
public void run() {
// here you can use the si
si.simulate(...);
}
}
然后将模拟器提交给线程池:
Simulator simulator = new Simulator(si);
...
exec.submit(simulator);
我的问题是在代码的某些部分我需要获取对当前运行的SimulatorThread的引用,但是指令(SimulatorThread)Thread.currentThread()给出了一个强制转换
您不应该将Thread
传递给ExecutorService
。它只是将它用作Runnable
(因为Thread
实现Runnable
)并且线程池启动其自己的线程并且永远不会在{{1}上调用start()
}}。如果您要延长SimulatorThread
,则需要直接致电Thread
而不将其提交至thread.start()
。 ExecutorService
implements Runnable
的上述模式更好。
答案 1 :(得分:1)
@Gray的答案是正确的,指出ExecutorService旨在使用自己的线程来执行Runnables,有时创建的线程甚至会被重用来运行不同的Runnables。
试图从(SimulatorThread) Thread.currentThread()
获取信息,就像'全局变量'反模式一样。最好在方法调用中传递'si'变量。
如果您确实需要线程安全的全局变量,请使用ThreadLocals:
public final class Simulator extends SimulatorRunnable {
public static final ThreadLocal<SimulatorInterface> currentSim = new ThreadLocal<>();
public Simulator(SimulatorInterface si) {
super(si);
}
public void run() {
currentSim.set(si)
try{
doStuff();
}
finally{
currentSim.unset();
}
}
private void doStuff()
{
SimulatorInterface si = Simulator.currentSim.get();
//....
}
}