threadpool抛出java.util.concurrent.futuretask不能施放到java.lang.com.

发布于 2025-02-13 11:33:23 字数 1815 浏览 0 评论 0原文

我有一个非常简单的程序:

    public static void main(String[] args) throws Exception {
        class MyThread2 implements Runnable{
            @Override
            public void run() {
                while (true) {
                    try {
                        if (Thread.interrupted()) {
                            System.out.println("Terminated!");
                            throw new InterruptedException();
                        }
                    } catch (InterruptedException e) {
                        return;
                    }
                }
            }
        }
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,
                2,
                1,
                TimeUnit.SECONDS,
                new PriorityBlockingQueue<>(),
                Executors.defaultThreadFactory());
        executor.submit(new MyThread2());
        executor.submit(new MyThread2());
        executor.submit(new MyThread2());
        executor.shutdownNow();
    }

在使用Maven运行它时,它可以打印:

[WARNING]
java.lang.ClassCastException: java.util.concurrent.FutureTask cannot be cast to java.lang.Comparable
    at java.util.concurrent.PriorityBlockingQueue.siftUpComparable (PriorityBlockingQueue.java:357)
    at java.util.concurrent.PriorityBlockingQueue.offer (PriorityBlockingQueue.java:489)
    at java.util.concurrent.ThreadPoolExecutor.execute (ThreadPoolExecutor.java:1371)
    at java.util.concurrent.AbstractExecutorService.submit (AbstractExecutorService.java:112)
    at MyThreadFactory.main (MyThreadFactory.java:33)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:254)
    at java.lang.Thread.run (Thread.java:748)

挂起。我在程序中没有任何PriorityBlockingQueue的“可比较”实现,此例外来自哪里?

I've got a very simple program:

    public static void main(String[] args) throws Exception {
        class MyThread2 implements Runnable{
            @Override
            public void run() {
                while (true) {
                    try {
                        if (Thread.interrupted()) {
                            System.out.println("Terminated!");
                            throw new InterruptedException();
                        }
                    } catch (InterruptedException e) {
                        return;
                    }
                }
            }
        }
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,
                2,
                1,
                TimeUnit.SECONDS,
                new PriorityBlockingQueue<>(),
                Executors.defaultThreadFactory());
        executor.submit(new MyThread2());
        executor.submit(new MyThread2());
        executor.submit(new MyThread2());
        executor.shutdownNow();
    }

On running it using maven, it prints:

[WARNING]
java.lang.ClassCastException: java.util.concurrent.FutureTask cannot be cast to java.lang.Comparable
    at java.util.concurrent.PriorityBlockingQueue.siftUpComparable (PriorityBlockingQueue.java:357)
    at java.util.concurrent.PriorityBlockingQueue.offer (PriorityBlockingQueue.java:489)
    at java.util.concurrent.ThreadPoolExecutor.execute (ThreadPoolExecutor.java:1371)
    at java.util.concurrent.AbstractExecutorService.submit (AbstractExecutorService.java:112)
    at MyThreadFactory.main (MyThreadFactory.java:33)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:254)
    at java.lang.Thread.run (Thread.java:748)

And hangs. I don't have any "Comparable" implementation for PriorityBlockingQueue in my program, where does this exception came from?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我不会写诗 2025-02-20 11:33:23

PriorityBlockingQueue期望可比元素,您的mythread2类无法提供。因此,您的程序中确实具有可比性,但这是内部的。

例如,如果您无法提供可比的元素,则将您的executor更改为linkedblockingqueue。或显然,找到一种“解释”如何比较提交任务的方法(通过实现可比)。


现在我考虑一下,如果API可以检测到这一点,那将是非常酷的。因此,如果您提供PriorityBlockingQueue并调用crist(new MyThread2())在编译时间提高(说mythread2不是可比)。不幸的是,在此API中并非如此,我也不认为这是可能的。

PriorityBlockingQueue expects comparable elements, which your MyThread2 class fails to provide. So you do have Comparable in your program, but it's an internal thing.

Change your executor to use LinkedBlockingQueue, if you can't provide comparable elements, for example. Or obviously, find a way to "explain" how to compare your tasks that you submit (by implementing Comparable).


Now that I think about it, it would have been very cool if the API could detect that. So if you provide a PriorityBlockingQueue and call submit(new MyThread2()), at compile time, this would have detected and a compile time error raised (saying that MyThread2 is not a Comparable). Unfortunately this is not the case in this API, nor I think it's possible at all.

空城之時有危險 2025-02-20 11:33:23

抛出异常,因为优先级阻止队列不知道,如何比较其元素。它不允许不可分配的对象。您有两个选项:

  1. 使队列元素实现可比较的
  2. 构造函数中的比较器,请

签名priorityblocking queue javadoc: https://docs.oracle.com/javase/7/docs/api/java/java/util/concurrent/concurrent/priorityblockingqueue.html

Exception is thrown, because priority blocking queue doesn't know, how to compare its elements. It does not permit non-comparable objects. You have two options:

  1. Make queue elements implement comparable
  2. Provide comparator for queue in constructor

Checkout PriorityBlocking queue javadoc: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/PriorityBlockingQueue.html

弥繁 2025-02-20 11:33:23

我得到了同样的例外,但是在某些情况下,我确实具有可比较的任务。我发现,如果称为小于或等于核心线程的数量,则提交作品。

Windows上的JDK版本是:

JAVA_RUNTIME_VERSION="21.0.1+12-LTS-29"
JAVA_VERSION="21.0.1"
JAVA_VERSION_DATE="2023-10-17"

这是我拥有的代码,并在底部输出。

public class TPEMain
{

    public static void main(String[] args)
    {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(4, 10, 10,
                TimeUnit.SECONDS, new PriorityBlockingQueue<Runnable>(20), 
                new ThreadPoolExecutor.CallerRunsPolicy());
        try
        {
            TestTask task = new TestTask("");
            Future<Boolean> fut = threadPoolExecutor.submit((Callable)task);
            Boolean res = fut.get();
            
            System.out.println(res);
            fut = threadPoolExecutor.submit((Callable)task);
            res = fut.get();
            System.out.println(res);
            
            fut = threadPoolExecutor.submit((Callable)task);
            res = fut.get();
            System.out.println(res);
            
            fut = threadPoolExecutor.submit((Callable)task);
            res = fut.get();
            System.out.println(res);
            
            fut = threadPoolExecutor.submit((Callable)task);
            res = fut.get();
            System.out.println(res);
            
            fut = threadPoolExecutor.submit((Callable)task);
            res = fut.get();
            System.out.println(res);
            
            fut = threadPoolExecutor.submit((Callable)task);
            res = fut.get();
            System.out.println(res);
        } catch (Throwable e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        
        try
        {
            TestTask task = new TestTask("");
            Future<TestTask> fut = threadPoolExecutor.submit(task, task);
            Boolean res = fut.get().status;
            System.out.println(res);

            fut = threadPoolExecutor.submit(task, task);
            res = fut.get().status;
            System.out.println(res);

            fut = threadPoolExecutor.submit(task, task);
            res = fut.get().status;
            System.out.println(res);

            fut = threadPoolExecutor.submit(task, task);
            res = fut.get().status;
            System.out.println(res);

            fut = threadPoolExecutor.submit(task, task);
            res = fut.get().status;
            System.out.println(res);

            fut = threadPoolExecutor.submit(task, task);
            res = fut.get().status;
            System.out.println(res);

            fut = threadPoolExecutor.submit(task, task);
            res = fut.get().status;
            System.out.println(res);
            
        } catch (Throwable e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        
        try
        {
            TestTask task = new TestTask("");
            Boolean res = null;
            
            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);

            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);

            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);

            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);

            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);

            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);

            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);


        }
        finally
        {
            threadPoolExecutor.shutdown();
        }
        
    }

}
class TestTask implements Callable<Boolean>, Comparable<TestTask>, Runnable
{

    String str = null;
    Boolean status = null;
    boolean completed = false;
    public TestTask(String string)
    {
        str = string;
    }

    @Override
    public int compareTo(TestTask o)
    {
        return str.compareTo(o.str);
    }

    @Override
    public Boolean call() throws Exception
    {
        long a = System.currentTimeMillis() % 2;
        if( a == 0)
            return false;
        if(a == 1)
            return true;
        return null;
    }

    @Override
    public void run()
    {
        try
        {
            this.status = this.call();
        } catch (Exception e)
        {
            throw new RuntimeException(e);
        }
        finally
        {
            this.completed = true;
        }
        
    }
    
}

输出:

true
true
true
false
java.lang.ClassCastException: class java.util.concurrent.FutureTask cannot be cast to class java.lang.Comparable (java.util.concurrent.FutureTask and java.lang.Comparable are in module java.base of loader 'bootstrap')
    at java.base/java.util.concurrent.PriorityBlockingQueue.siftUpComparable(PriorityBlockingQueue.java:349)
    at java.base/java.util.concurrent.PriorityBlockingQueue.offer(PriorityBlockingQueue.java:475)
    at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1368)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
    at threadpool.TPEMain.main(TPEMain.java:37)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
java.lang.ClassCastException: class java.util.concurrent.FutureTask cannot be cast to class java.lang.Comparable (java.util.concurrent.FutureTask and java.lang.Comparable are in module java.base of loader 'bootstrap')
    at java.base/java.util.concurrent.PriorityBlockingQueue.siftUpComparable(PriorityBlockingQueue.java:349)
    at java.base/java.util.concurrent.PriorityBlockingQueue.offer(PriorityBlockingQueue.java:475)
    at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1368)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at threadpool.TPEMain.main(TPEMain.java:59)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
true:true
false:true
false:true
false:true
true:true
false:true
false:true

I got the same exception but for a little bit different case where I do have the task implement Comparable. What I found is that submit works if called less than or equal to the number of core threads.

JDK version on Windows is:

JAVA_RUNTIME_VERSION="21.0.1+12-LTS-29"
JAVA_VERSION="21.0.1"
JAVA_VERSION_DATE="2023-10-17"

Here is the code I have and output at the bottom.

public class TPEMain
{

    public static void main(String[] args)
    {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(4, 10, 10,
                TimeUnit.SECONDS, new PriorityBlockingQueue<Runnable>(20), 
                new ThreadPoolExecutor.CallerRunsPolicy());
        try
        {
            TestTask task = new TestTask("");
            Future<Boolean> fut = threadPoolExecutor.submit((Callable)task);
            Boolean res = fut.get();
            
            System.out.println(res);
            fut = threadPoolExecutor.submit((Callable)task);
            res = fut.get();
            System.out.println(res);
            
            fut = threadPoolExecutor.submit((Callable)task);
            res = fut.get();
            System.out.println(res);
            
            fut = threadPoolExecutor.submit((Callable)task);
            res = fut.get();
            System.out.println(res);
            
            fut = threadPoolExecutor.submit((Callable)task);
            res = fut.get();
            System.out.println(res);
            
            fut = threadPoolExecutor.submit((Callable)task);
            res = fut.get();
            System.out.println(res);
            
            fut = threadPoolExecutor.submit((Callable)task);
            res = fut.get();
            System.out.println(res);
        } catch (Throwable e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        
        try
        {
            TestTask task = new TestTask("");
            Future<TestTask> fut = threadPoolExecutor.submit(task, task);
            Boolean res = fut.get().status;
            System.out.println(res);

            fut = threadPoolExecutor.submit(task, task);
            res = fut.get().status;
            System.out.println(res);

            fut = threadPoolExecutor.submit(task, task);
            res = fut.get().status;
            System.out.println(res);

            fut = threadPoolExecutor.submit(task, task);
            res = fut.get().status;
            System.out.println(res);

            fut = threadPoolExecutor.submit(task, task);
            res = fut.get().status;
            System.out.println(res);

            fut = threadPoolExecutor.submit(task, task);
            res = fut.get().status;
            System.out.println(res);

            fut = threadPoolExecutor.submit(task, task);
            res = fut.get().status;
            System.out.println(res);
            
        } catch (Throwable e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        
        try
        {
            TestTask task = new TestTask("");
            Boolean res = null;
            
            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);

            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);

            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);

            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);

            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);

            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);

            task = new TestTask("");
            threadPoolExecutor.execute(task);
            while(task.completed != true)
            {
                res = task.status;
            }
            System.out.println(res +":"+ task.completed);


        }
        finally
        {
            threadPoolExecutor.shutdown();
        }
        
    }

}
class TestTask implements Callable<Boolean>, Comparable<TestTask>, Runnable
{

    String str = null;
    Boolean status = null;
    boolean completed = false;
    public TestTask(String string)
    {
        str = string;
    }

    @Override
    public int compareTo(TestTask o)
    {
        return str.compareTo(o.str);
    }

    @Override
    public Boolean call() throws Exception
    {
        long a = System.currentTimeMillis() % 2;
        if( a == 0)
            return false;
        if(a == 1)
            return true;
        return null;
    }

    @Override
    public void run()
    {
        try
        {
            this.status = this.call();
        } catch (Exception e)
        {
            throw new RuntimeException(e);
        }
        finally
        {
            this.completed = true;
        }
        
    }
    
}

Output:

true
true
true
false
java.lang.ClassCastException: class java.util.concurrent.FutureTask cannot be cast to class java.lang.Comparable (java.util.concurrent.FutureTask and java.lang.Comparable are in module java.base of loader 'bootstrap')
    at java.base/java.util.concurrent.PriorityBlockingQueue.siftUpComparable(PriorityBlockingQueue.java:349)
    at java.base/java.util.concurrent.PriorityBlockingQueue.offer(PriorityBlockingQueue.java:475)
    at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1368)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
    at threadpool.TPEMain.main(TPEMain.java:37)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
java.lang.ClassCastException: class java.util.concurrent.FutureTask cannot be cast to class java.lang.Comparable (java.util.concurrent.FutureTask and java.lang.Comparable are in module java.base of loader 'bootstrap')
    at java.base/java.util.concurrent.PriorityBlockingQueue.siftUpComparable(PriorityBlockingQueue.java:349)
    at java.base/java.util.concurrent.PriorityBlockingQueue.offer(PriorityBlockingQueue.java:475)
    at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1368)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at threadpool.TPEMain.main(TPEMain.java:59)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
true:true
false:true
false:true
false:true
true:true
false:true
false:true
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文