1

对于我的论文,我正在研究离散事件系统模拟器。模拟包含一组,SimulatorThread extends Thread其动作在于Event将 s 调度到Simulator. 每一个都通过 与SimulatorThread交互。SimulatorSimulatorInterface

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返回SimulatorThread.

事实上,我尝试使用琐碎的SimulatorThreadFactory extends ThreadFactory

public class SimulatorThreadFactory implements ThreadFactory {

    @Override
    public Thread newThread(Runnable r) {
        return new SimulatorThread(new SimulatorInterface());
    }
}

有了这个,我获得了前面引用的输出“类 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);
    }
}

那么,如果它的参数是 a ,我如何访问方法内的“SimulatorThread”的属性“SimulatorInterface”newThread以创建a ?SimulatorThreadRunnable

4

2 回答 2

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() 给出了强制转换执行

您不应该将 a 传递ThreadExecutorService. 它只是将它用作Runnable(因为Threadimplements Runnable)并且线程池启动它自己的线程并且永远不会调用start()你的SimulatorThread. 如果您正在扩展,Thread那么您需要thread.start()直接调用而不是将其提交给ExecutorService. 上面的implements Runnablewith an模式ExecutorService更好。

于 2013-04-23T13:49:25.553 回答
1

@Gray's answer is correct, pointing out that the ExecutorService is designed to use its own threads to execute your Runnables, and sometimes created threads will even be reused to run different Runnables.

Trying to get information from (SimulatorThread) Thread.currentThread() smells like a 'global variable' anti-pattern. Better to pass the 'si' variable along in method calls.

If you really want global variables that are thread-safe, use 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();
      //.... 
   }
 }
于 2013-04-23T14:23:55.537 回答