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

时间:2018-03-09 16:30:31

标签: java multithreading

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

HashMap<String, Callable>似乎适合存储线程并确保每个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);
    }
}

2 个答案:

答案 0 :(得分:1)

如果您的问题是在线程完成其工作时从Map中删除这对(key,Callable)。在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);
    }
}

答案 1 :(得分:0)

您可以将Callable包裹在自己的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();
            }
        }
    }
}