Java为每个数据库行创建唯一线程

Java为每个数据库行创建唯一线程,java,multithreading,Java,Multithreading,我需要每x秒轮询一次数据库,并取出需要处理的记录。我将为每一行启动一个线程。下次轮询时,线程可能尚未完成。我不想为同一ID启动另一个线程,因为它仍在处理 HashMap似乎适合于存储线程,并确保每个ID只存在一个线程。我不明白的是,在线程完成后如何删除线程 我的理解是,如果我在线程上等待,那么它将阻塞主线程,轮询将不会继续 我已经尝试了下面的代码,它是有效的,但是随着更多任务的到来,HashMap将继续增长。有可能在当天晚些时候重新处理该行 HashMap<String, Callable

我需要每x秒轮询一次数据库,并取出需要处理的记录。我将为每一行启动一个线程。下次轮询时,线程可能尚未完成。我不想为同一ID启动另一个线程,因为它仍在处理

HashMap
似乎适合于存储线程,并确保每个ID只存在一个线程。我不明白的是,在线程完成后如何删除线程

我的理解是,如果我在线程上等待,那么它将阻塞主线程,轮询将不会继续

我已经尝试了下面的代码,它是有效的,但是随着更多任务的到来,HashMap将继续增长。有可能在当天晚些时候重新处理该行

HashMap<String, Callable<String>> callables = new HashMap<String, Callable<String>>();
for(int i =0; i < 10; i++)
{
    for(int j =0; j < 10; j++)
    {
        String key = Integer.toString(j);
        if(!callables.containsKey(key))
        {
            callables.put(key, new Callable<String>() {
                public String call() throws Exception {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Inside task");
                    return "Task Completed";
                }
            });
            try
            {
                callables.get(key).call();
            }
            catch(Exception ex){
                ex.printStackTrace();
            }
        }
        else
            System.out.println("Task skipped: " + j);
    }
}
HashMap callables=newhashmap();
对于(int i=0;i<10;i++)
{
对于(int j=0;j<10;j++)
{
字符串key=Integer.toString(j);
如果(!callables.containsKey(键))
{
put(key,newcallable()){
公共字符串调用()引发异常{
试一试{
睡眠(500);
}捕捉(中断异常e){
e、 printStackTrace();
}
System.out.println(“内部任务”);
返回“任务完成”;
}
});
尝试
{
callables.get(key.call();
}
捕获(例外情况除外){
例如printStackTrace();
}
}
其他的
System.out.println(“跳过任务:+j”);
}
}

如果您的问题是在线程完成其工作后从映射中删除该对(键,可调用)。在其Call()函数的末尾调用remove()

HashMap<String, Callable<String>> callables = new HashMap<String, 
Callable<String>>();
for(int i =0; i < 10; i++) {
    for(int j =0; j < 10; j++) {
        String key = Integer.toString(j);
        if(!callables.containsKey(key)) {
            callables.put(key, new Callable<String>() {
                final String mKey = key; //store the current key
                public String call() throws Exception {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Inside task");
                    callables.remove(mKey); //Remove the thread from the Map
                    return "Task Completed";
                }
            });
            try {
                callables.get(key).call();
            }
            catch(Exception ex) {
                ex.printStackTrace();
            }
        }
        else
            System.out.println("Task skipped: " + j);
    }
}
HashMap callables=newhashmap();
对于(int i=0;i<10;i++){
对于(int j=0;j<10;j++){
字符串key=Integer.toString(j);
如果(!callables.containsKey(键)){
put(key,newcallable()){
最后一个字符串mKey=key;//存储当前密钥
公共字符串调用()引发异常{
试一试{
睡眠(500);
}捕捉(中断异常e){
e、 printStackTrace();
}
System.out.println(“内部任务”);
callables.remove(mKey);//从映射中删除线程
返回“任务完成”;
}
});
试一试{
callables.get(key.call();
}
捕获(例外情况除外){
例如printStackTrace();
}
}
其他的
System.out.println(“跳过任务:+j”);
}
}

您可以将
Callable
s包装在自己的
Callable

HashMap<String, Callable<String>> callables = new HashMap<>();

public void oneOnly(String id, Callable<String> callable) {
    if (!callables.containsKey(id)) {
        // Wrap the callable in my own.
        callables.put(id, new Callable<String>() {
            public String call() throws Exception {
                String result = callable.call();
                // Remove when finished.
                callables.remove(id);
                return result;
            }
        });

    }
}

public void test(String[] args) throws Exception {
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            String key = Integer.toString(j);
            oneOnly(key, new Callable<String>() {
                public String call() throws Exception {
                    System.out.println("Inside task");
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return "Task Completed";
                }
            });
            try {
                callables.get(key).call();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}
HashMap callables=newhashmap();
public void oneOnly(字符串id,可调用){
如果(!callables.containsKey(id)){
//把电话包在我自己的里面。
put(id,newcallable()){
公共字符串调用()引发异常{
String result=callable.call();
//完成后移除。
callables.remove(id);
返回结果;
}
});
}
}
公共无效测试(字符串[]args)引发异常{
对于(int i=0;i<10;i++){
对于(int j=0;j<10;j++){
字符串key=Integer.toString(j);
oneOnly(键,新可调用(){
公共字符串调用()引发异常{
System.out.println(“内部任务”);
试一试{
睡眠(500);
}捕捉(中断异常e){
e、 printStackTrace();
}
返回“任务完成”;
}
});
试一试{
callables.get(key.call();
}捕获(例外情况除外){
例如printStackTrace();
}
}
}
}

为什么要将整数转换为字符串?为什么不直接使用整数作为键呢?双循环的作用是什么?我正在设计一个例子来帮助说明这个问题。我的实际密钥将是一个字符串。双循环是为了证明下一次通过“键”将不再被处理,因为您需要一个线程池。您还需要忘记线程,使用Executor/ThreadPool,等等。这听起来像是一场即将发生的灾难。我不认为你被允许访问lambda之外的物品。“我不明白你是怎么把钥匙放进mKey的?”理查德宾宁顿编辑后在mKey里加了钥匙谢谢你,先生!我非常感激!