我目前正在开发一个数据库集成日常文件传输调度表单应用程序,用于运营业务。为了能够控制并访问特定的时间表,我决定为每个时间表创建一个线程,以便可以按需停止或重新启动特定的时间表。为了实现这一点,我编写了一个单独的类,其中包括一个自定义线程类及其构造函数,一个用于创建和运行线程实例的主类,以及另一个包含每日调度的runnable方法的类。为了能够访问特定的线程,我尝试实现ConcurrentHashMap来同步哈希码和创建的线程的名称以及ThreadGroup。当我创建一个线程时,我能够将线程的名称和哈希码与ThreadGroup一起传递给ConcurrentHashMap。但是,当我创建第二个或第三个线程时,我发现指定的名称和已指定的线程的哈希码正在发生变化。我在上面解释过的课程如下所示。
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);
}
}
}
}
}
我已经为每个线程运行了两个不同的计划。可以看到活动线程的输出
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
正如在上面的输出中可以看到的,名为Test 2的Thread的名称和hashCode与已放入threadMap(hashMap)的值不对应。我希望能够为特定操作设置静态名称和哈希码,以便通过访问每个特定操作来停止,暂停,恢复或删除。因此,我想知道可能导致问题的原因,或者我以错误的方式实施了什么。