2013-02-27 75 views
1

在Java不兼容的,我得到一个转换异常:

java.lang.ClassCastException: java.util.concurrent.ThreadPoolExecutor$Worker 
incompatible with com.myco.TaskListEntry 
at com.myco.JobThreadFactory.newThread(JobThreadFactory.java:17) 

下面的代码:

public class JobThreadFactory implements ThreadFactory { 
    @Override 
    public Thread newThread(Runnable r) { 
     TaskListEntry entry = (TaskListEntry)r; //<== Cast exception! 
     return new Thread(r, "Thread for " + entry.toString()); 
    } 
} 

@DisallowConcurrentExecution 
public class WorksheetSessionJob implements Job { 
    private List<TaskListEntry> taskListEntries; 

    @Override 
    public void execute(JobExecutionContext jobContext) throws JobExecutionException { 
     ThreadFactory threadFactory = new JobThreadFactory(); 
     ExecutorService executor = Executors.newCachedThreadPool(threadFactory); 
     for(TaskListEntry nextEntry : getWorkListEntries()) { 
      executor.execute(nextEntry); 
     } 
    } 

    private List<TaskListEntry> getWorkListEntries() { 
     List<TaskListEntry> entries = new ArrayList<TaskListEntry>(); 

     // TODO Get rows from DB - for now, make something up to test with 
     //-- beginning of fake data creation ---------- 
     TaskListEntry entry = new TaskListEntry("0022", "04590150560", "DI_MODULAR", 1); 
     entries.add(entry); 
     entry = new TaskListEntry("0007", "04590150560", "DI_MODULAR", 2); 
     entries.add(entry); 
     //-- end of fake data creation ---------------- 

     return entries; 
    } 

} 

public class TaskListEntry implements Runnable { 
    private String worksheetNumber; 
    private String specimenNumber; 
    private String instrumentName; 
    private int  id; 

    public TaskListEntry(String worksheetNumber, 
      String specimenNumber, String instrumentName, int id) { 
     super(); 
     this.worksheetNumber = worksheetNumber; 
     this.specimenNumber = specimenNumber; 
     this.instrumentName = instrumentName; 
     this.id = id; 
    } 

    @Override 
    synchronized public void run() { 
     // executor in my Job should have created a thread for me to run in 
     //-- TESTING ONLY ------------- 
     try { 
      Thread.sleep(10000); //force execution to another thread? 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     //-- END OF TESTING ----------- 
    } 

} 

为什么不是我的TaskListEntry runnable被发送?我需要使用该类的值来命名相应的线程。我究竟做错了什么?!

回答

4

您正在收到铸造问题,因为当调用线程工厂时,您的Runnable未与ThreadPoolExecutor$Worker类关联。 WorkerRunnable是一个内部执行程序类,它将持有TaskListEntry实例的内部BlockingQueue出列任务。您的任务无法通过设计与特定的线程关联。如果你将100k个任务提交到队列中,你不希望它产生10万个线程 - 这就是使用线程池的关键。

如果您试图以某种方式跟踪哪些线程正在处理哪些任务,我会建议在TaskListEntry.run()方法内记录线程ID(Thread.currentThread().getId())。但是,如果您试图在线程名称中以某种方式查看每个任务,那么您并不理解线程池如何工作。通常,我使用ThreadFactory在池线程上设置名称来标识池名称。像"TaskListEntry pool-1"或其他什么东西将是一个合适的线程名称在这里。

如果您更详细地解释您想要完成的名称,我们可能会提供更多帮助。

+0

感谢您的回复。我知道你在说什么关于池使用更小的线程实例反复。我试图做的是有一个更有意义的方式来查看在调试时发生了什么/发生了什么,特别是在问题发生后查看日志文件。对此有何建议? – Mark 2013-02-28 13:21:06

+0

正如我在答案中提到的那样,我会在线程池线程上设置一个好名字,以显示它们与TaskListEntry处理相关联,并在日志中记录线程ID以显示正在处理的内容。这就是你所能做的一切。 – Gray 2013-02-28 13:22:57