Sanjana
Sanjana

Reputation: 467

Multithreading inside for loop

I am trying to read the multiple files from a directory and create a separate thread for every file.While iterating the loop, the anonymous inner class cannot use non final variables.

My question is how to create multiple threads inside a loop.(I am required to manually create threads for each file, cant use executor service or something else)

class de
{

    void commit(File x){

       int sum =0;
       try{
           FileInputStream fin = new FileInputStream(x);
           byte[]b= new byte[5000];
           fin.read(b);
           for (byte digit:b){
               sum=digit+sum;
           }
           System.out.println(sum);
       }
       catch(Exception e){}
    }
    public static void main (String args[]){    
        File f = new File("C:\\Users\\Sanjana\\workspace\\IO\\Numbers");
        File []store = f.listFiles( new FilenameFilter(){
            public boolean accept(File f, String name){
                return name.endsWith("txt");
            }
        });

       for (File x: store){   
           Thread t = new Thread(){
               public void run (){
               //new de().commit(x); /**/Error here non final variable x**
               }
           };
       }
    }    
}

Upvotes: 3

Views: 3071

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285450

Change

for (File x: store)

to

for (final File x: store)

Edit you state:

Its working but final variables are constant, here x is changing to each element of store.howz that working

x is a parameter of the for-each loop and can be declared final as per the definition of for-each loop. Each time the loop loops, it's as if x is created anew.


Per the JLS 14.14.2 section on the enhanced for loop:

The enhanced for statement is equivalent to a basic for statement of the form:

for (I #i = Expression.iterator(); #i.hasNext(); ) {
    VariableModifiersopt TargetType Identifier =
        (TargetType) #i.next();
    Statement
}

So this tells me that final would fit in like so:

for (I #i = Expression.iterator(); #i.hasNext(); ) {
    final VariableModifiersopt TargetType Identifier =
        (TargetType) #i.next();
    Statement
}

So the x is really the Identifier above and is in actuality re-declared with each iteration of the loop.

In your code, I'm thinking that it's equivalent to:

  for (Iterator<File> iterator = Arrays.asList(scores).iterator(); iterator.hasNext();) {
     final File file = iterator.next();
     new Thread(new Runnable() {
        public void run() {
           new de().commit(file);
        }
     }).start();  
  }

Edit 2
Note that your use of Thread can be improved, that you should get in the habit of using a Runnable:

   for (final File x: store){   
       new Thread(new Runnable() {

         @Override
         public void run() {
           new de().commit(x);  // "de" should be "De" since it is a class
         }
       }).start();
    }

Upvotes: 4

Related Questions