S tavakoli
S tavakoli

Reputation: 21

Exception in thread "main" java.lang.ClassCastException: cannot be cast to java.util.concurrent.Callable

i have an array of integers and i want to calculate sum of each integer^2 in multi thread way. i wrote the program and when i run it i get an exception. The program is as follows:

package ir.org.acm.multithreadpower;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class Main3 {
    public static volatile int[] a;
    public static int i = 0;
    public static Collection tasks=new ArrayList();
    public static int sum=0;

    static{
        int length=9;
        a=new int[length];
        for(int k=0;k<length;k++)
            a[k]=k;
    }
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(8);
        new Main3().doJob(executor);
        executor.invokeAll(tasks);
        System.out.println(sum);


    }
    public void doJob(ExecutorService executor) throws Exception{

        for(int m=0;m<(a.length);m++) {
            tasks.add(new Runnable() {
                @Override
                public void run() {
                    a[i] = a[i] * a[i];
                    i++;
                }
            });
       }

        for (int k = 0; k < a.length; k++)
            sum += k;

        executor.shutdown();

    }
}

the program throws a run-time exception:

Exception in thread "main" java.lang.ClassCastException: ir.org.acm.multithreadpower.Main3$2 cannot be cast to java.util.concurrent.Callable
    at java.util.concurrent.AbstractExecutorService.invokeAll(AbstractExecutorService.java:235)
    at ir.org.acm.multithreadpower.Main3.main(Main3.java:35)

i googled this issue but could not figure out this problem thanks for your help.

regards,

Upvotes: 2

Views: 10711

Answers (2)

A Joshi
A Joshi

Reputation: 151

You should also move executor.shutdown(); from the method doJob to after executor.invokeAll(tasks);

Upvotes: 0

Boris the Spider
Boris the Spider

Reputation: 61138

Your problem is here:

public static Collection tasks=new ArrayList();

This is a rawtype, which means the compiler cannot ensure safety when using this Collection.

How, lets look at Executor.invokeAll, the signature is:

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)

So your Collection needs to contain Callable<T> (where T doesn't matter).

Now, lets look at your code:

public void doJob(ExecutorService executor) throws Exception {
    for(int m=0;m<(a.length);m++) {
        tasks.add(new Runnable() {
                    //^ here

So you are adding Runnable. Obviously Runnable is not Callable.

TL;DR:

Change:

public static Collection tasks = new ArrayList();

to:

public static Collection<Callable<Void>> tasks = new ArrayList<>();

then you'll have many compiler errors to fix.


When you compiled this code, you would have gotten a warning such as:

[WARNING] ...App.java:[17,27] unchecked method invocation: method invokeAll in interface java.util.concurrent.ExecutorService is applied to given types
  required: java.util.Collection<? extends java.util.concurrent.Callable<T>>
  found: java.util.Collection
[WARNING] ...App.java:[17,28] unchecked conversion
  required: java.util.Collection<? extends java.util.concurrent.Callable<T>>
  found:    java.util.Collection

don't ignore compiler warnings.

Upvotes: 1

Related Questions