0

I am currently working on a DB integrated daily file transfer scheduling form application for operational business use. In order to be able to control and have access to specific schedules, I have decided to create a thread for each schedule so that a specific schedule could be stopped, or restarted on demand. To achieve this, I have written a separate class which includes a custom thread class and its constructor, a main class to create and run an instance of thread and another class that includes the runnable method of daily scheduling. In order to be able to access specific threads, I have tried to implement a ConcurrentHashMap to synchronise the hashcodes and the names of the threads created, along with a ThreadGroup. When I create a thread, I am able to pass the name and the hashcode of the thread to the ConcurrentHashMap, along with the ThreadGroup. However, when I create the second or the third thread, I have discovered that the specified names and the hashcodes of the threads that have been specified are changing. The class that I have explained above could be seen below.

java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ThreadRun
{
   static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(20);  
   static String name, s, d;
   static int h = 0;
   static int m = 0;
   static ThreadGroup tg = new ThreadGroup("ThreadGroup");
   static Map<String,Object> threadMap = 
           Collections.synchronizedMap(new HashMap<String,Object>(30));

   public void start (String n, String src, String dest, int hour, int min) 
   {
            name = n;
            s = src;
            d = dest;
            h = hour;
            m = min;

            MyThread mt = new MyThread(tg,name,s,d,h,m);
            mt.setName(name);

            threadMap.put(name, mt.hashCode());
            mt.start();
            System.out.println("Thread: " + mt.getName() + " is started!");
            System.out.println("getThread");
            getThread(tg);
            System.out.println("getAllThreadMap");
            getAllThreadMap();

      }


   void getAllThreadMap()
   {
       Iterator it = threadMap.entrySet().iterator();
       while(it.hasNext())
       {
           Map.Entry pair = (Map.Entry)it.next();
           System.out.println(pair.getKey() + " = " + pair.getValue());
       }
   }

   Thread[] getAllThreads(ThreadGroup tg) {
    tg = Thread.currentThread().getThreadGroup();
    final ThreadMXBean thbean = ManagementFactory.getThreadMXBean( );
  //  System.out.println("Group active count: "+ tg.activeCount());
    int nAlloc = thbean.getThreadCount( ) + 2;
    int n = 0;
    Thread[] threads;
    do {
        nAlloc *= 2;
        threads = new Thread[ nAlloc ];
        n = tg.enumerate( threads, true );
    } while ( n == nAlloc );
    return java.util.Arrays.copyOf( threads, n );
} //getting all the active threads to an array

   void getThread(ThreadGroup g) //getting a specific thread
   {
    final Thread[] threads = getAllThreads(g);
    for ( Thread thread : threads )
    {
        System.out.println("ThreadName = " + thread.getName() + " ThreadHash = " +thread.hashCode());
    }
}

  static class MyThread extends Thread{

      MyThread(ThreadGroup tg, String name, String src, String dest, int hour, int min)
      {
            super(tg,name);
      }

      @Override
         public void run () // run thread
        {
            ScheduleControl sc = new ScheduleControl();
            sc.scheduleDaily();
        }


class ScheduleControl {


   public void scheduleDaily() {
     final Runnable task = new Runnable() {
         @Override
       public void run() 
       { 

             try {
                 t(s,d,h,m);
             } catch (IOException ex) {
                 Logger.getLogger(ThreadRun.class.getName()).log(Level.SEVERE, null, ex);
             }

       }
     };

        LocalDateTime localNow = LocalDateTime.now();
        ZoneId currentZone = ZoneId.of("CET");
        ZonedDateTime zonedNow = ZonedDateTime.of(localNow, currentZone);

        ZonedDateTime zonedNext5 = zonedNow.withHour(h).withMinute(m).withSecond(0);

        if(zonedNow.compareTo(zonedNext5) > 0)
        zonedNext5 = zonedNext5.plusDays(1);

        Duration duration = Duration.between(zonedNow, zonedNext5);
        long initalDelay = duration.getSeconds();

        //System.out.println("Schedule is started at\n" + LocalDateTime.now().getHour()+ ":" + LocalDateTime.now().getMinute());
       // System.out.println("Initial delay: " + initalDelay/60/60);
        final ScheduledFuture<?> scheduleHandle =
        scheduler.scheduleAtFixedRate(task, initalDelay , 24*60*60, SECONDS);

      /*   scheduler.schedule(new Runnable() {
      @Override
       public void run() 
       {
           scheduleHandle.cancel(true);
       }
     }, 60*60, SECONDS);*/
   }
public Runnable t (String source, String destin, int h, int m) throws IOException
       {
           File srcF = new File(""+source);
           File destF = new File(""+destin);
           copyFolder(srcF,destF);
           System.out.println("Schedule finished at: " +LocalDateTime.now().getHour() + ":" +LocalDateTime.now().getMinute() + ":" +LocalDateTime.now().getSecond());
           return null;
       }
        public void copyFolder(File src, File dest)
        throws IOException{

        if(src.isDirectory()){

            //if directory not exists, create it
            if(!dest.exists()){
               dest.mkdir();
               System.out.println("Directory copied from " 
                              + src + "  to " + dest);
            }

            //list all the directory contents
            String files[] = src.list();

            for (String file : files) {
               //construct the src and dest file structure
               File srcFile = new File(src, file);
               File destFile = new File(dest, file);
               //recursive copy
               copyFolder(srcFile,destFile);
            }
        }
        else
        {
            OutputStream out;
                try ( //if file, then copy it
                //Use bytes stream to support all file 

                    InputStream in = new FileInputStream(src)) {
                    out = new FileOutputStream(dest);
                    byte[] buffer = new byte[1024];
                    int length;
                    //copy the file content in bytes
                    while ((length = in.read(buffer)) > 0){
                        out.write(buffer, 0, length);
                }
                }
                out.close();
                System.out.println("File copied from " + src + " to " + dest);
            }
        }
    }
  }
}

I have activated two different schedules for each to be run by a thread. The output of the active threads could be seen

Thread: Test 1 is started! 
getThread
ThreadName = AWT-EventQueue-0 ThreadHash = 18329106
ThreadName = DestroyJavaVM ThreadHash = 21388846
ThreadName = Test 1 ThreadHash = 17676897
getAllThreadMap
Test 1 = 17676897
Thread: Test 2 is started!
getThread
ThreadName = AWT-EventQueue-0 ThreadHash = 18329106
ThreadName = DestroyJavaVM ThreadHash = 21388846
ThreadName = pool-1-thread-1 ThreadHash = 6119842 
ThreadName = Test 2 ThreadHash = 2586910
getAllThreadMap
Test 2 = 2586910
Test 1 = 17676897

As it could be seen in the output above, the name and the hashCode of the Thread named Test 2 is not correspondent to the values that have been put into the threadMap(hashMap). I would like to be able to have static names and hashcodes for specific operation so that I can stop, pause, resume or delete by accessing each specifically. Thus I wonder what might be causing the problem, or what I have implemented in a wrong way.

JacomusA
  • 1
  • 3
  • Why not just hold a reference to the thread object? – Melih Yıldız' Aug 05 '15 at 15:47
  • What do you mean by holding a reference to the thread object? I am holding the hashcode and the name in a hashmap, along with adding the threads into the ThreadGroup, the problem is that once the second thread is being created, the first's hashcode and the name is changing. I either need to find what causes this, or find a way to synchronise the created threads' references with the hashmap. – JacomusA Aug 06 '15 at 07:50
  • I understood the problem. My suggestion is adding `mt` to the map instead of `mt.hashCode()`. this would reason a memory issue tho – Melih Yıldız' Aug 06 '15 at 14:37
  • Thanks for your help. The pool size would not exceed the thread amount of 10 or 15 so. Thus I don't think it would be that much of a problem. I will try to implement suggestion. – JacomusA Aug 07 '15 at 07:49

0 Answers0