2013-02-27 73 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