我目前正在开发一个数据库集成的每日文件传输调度表单应用程序,以供运营业务使用。为了能够控制和访问特定的计划,我决定为每个计划创建一个线程,以便可以停止特定的计划,或者按需重新启动。为此,我编写了一个单独的类,其中包括一个自定义线程类及其构造函数、一个用于创建和运行线程实例的主类以及另一个包含日常调度的可运行方法的类。为了能够访问特定线程,我尝试实现一个 ConcurrentHashMap 来同步哈希码和创建的线程的名称,以及一个 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 的线程的名称和 hashCode 与放入 threadMap(hashMap) 的值不对应。我希望能够为特定操作提供静态名称和哈希码,以便我可以通过专门访问每个操作来停止、暂停、恢复或删除。因此,我想知道可能导致问题的原因,或者我以错误的方式实施了什么。