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.
import 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.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;
import static sun.misc.ThreadGroupUtils.getRootThreadGroup;
public class ThreadRun
{
static String name, s, d;
static int h = 0;
static int m = 0;
ThreadGroup tg = Thread.currentThread().getThreadGroup();
Thread[] threads;
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);
mt.start ();
System.out.println("Thread: " + mt.getName() + "is started!");
getThread();
}
Thread[] getAllThreads(ThreadGroup tg) {
// tg = Thread.currentThread().getThreadGroup();
final ThreadMXBean thbean = ManagementFactory.getThreadMXBean( );
int nAlloc = thbean.getThreadCount( ) + 1;
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() //getting a specific thread
{
final Thread[] threads = getAllThreads(tg);
for ( Thread thread : threads )
System.out.println("ThreadName = " + thread.getName());
}
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();
//System.out.println ("My name is: " + getName ());
}
//SCHEDULE ZAMAZEENGO
class ScheduleControl {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(20);
public void scheduleDaily() {
final Runnable task = new Runnable() {
@Override
public void run()
{
try {
t(s,d,h,m);
} catch (IOException ex) {
Logger.getLogger(MyThread.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 types
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!
ThreadName = AWT-EventQueue-0
ThreadName = DestroyJavaVM
ThreadName = Test 1
Schedule is started at 12:
Thread: Test 2 is started!
ThreadName = AWT-EventQueue-0
ThreadName = DestroyJavaVM
ThreadName = pool-1-thread-1
ThreadName = pool-1-thread-2
ThreadName = Test 2
Schedule is started at
12:25
As it could be seen in the output above, there are three (3) threads instead of two and the specified name has been changed. 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.
via
Chebli Mohamed