【问题标题】:Java Exception: ThreadPoolExecutor$Worker incompatible with com.myco.TaskListEntryJava 异常:ThreadPoolExecutor$Worker 与 com.myco.TaskListEntry 不兼容
【发布时间】:2013-02-27 22:12:08
【问题描述】:

在 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?我需要使用该类中的值来命名相应的线程。我究竟做错了什么?!

【问题讨论】:

    标签: java multithreading naming


    【解决方案1】:

    您遇到了转换问题,因为当调用线程工厂时,您的 RunnableThreadPoolExecutor$Worker 类没有关联。 Worker Runnable 是一个内部执行器类,它从包含您的 TaskListEntry 实例的内部 BlockingQueue 中取出任务。您的任务无法通过设计与特定线程相关联。如果您将 10 万个任务提交到队列中,您不会希望它产生 10 万个线程——这就是使用线程池的全部意义所在。

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

    如果您详细说明您在名称方面要完成的工作,我们可能会提供更多帮助。

    【讨论】:

    • 感谢您的回复。我理解你对池的说法,一遍又一遍地使用较小的 Thread 实例集。我想做的是有一种更有意义的方式来查看调试时正在发生/发生的事情,尤其是在出现问题后查看日志文件。有什么建议吗?
    • 正如我在回答 Mark 中提到的,我会在线程池线程上设置一个好名称,以显示它们与 TaskListEntry 处理相关联,并将线程 ID 记录到日志中显示正在做什么。这就是你所能做的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多