/****************************************************************************
 * Copyright (C) 2021 ecsec GmbH.
 * All rights reserved.
 * Contact: ecsec GmbH (info@ecsec.de)
 *
 * This file may be used in accordance with the terms and conditions
 * contained in a signed written agreement between you and ecsec GmbH.
 *
 ***************************************************************************/

package org.openecard.common.util;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;


/**
 *
 * @author Tobias Wich
 * @param <Key>
 */
public class ThreadManager <Key> {

    private static final long DEFAULT_WAIT = 5000;

    private final AtomicInteger threadNumber;
    private final ThreadGroup tg;
    private final Map<Key, Thread> threads;

    public ThreadManager(String threadGroupName) {
	this.threadNumber = new AtomicInteger(0);
	this.tg = new ThreadGroup(threadGroupName);
	this.threads = new HashMap<>();
    }

    public void submit(Key key, Runnable job) {
	synchronized (threads) {
	    String name = String.format("%s-%d", key.toString(), threadNumber.incrementAndGet());
	    Thread t = new Thread(tg, job, name);
	    t.start();
	    threads.put(key, t);
	}
    }

    public void stopThread(Key key) throws InterruptedException {
	stopThread(key, DEFAULT_WAIT);
    }

    public void stopThread(Key key, long maxWaitTime) throws InterruptedException {
	Thread t;
	synchronized (threads) {
	    t = threads.remove(key);
	}
	if (t != null) {
	    stopThread(t, maxWaitTime);
	}
    }

    private void stopThread(Thread t, long maxWaitTime) throws InterruptedException {
	t.interrupt();
	t.join(maxWaitTime);
    }

    public void stopThreads(long maxWaitTime) throws InterruptedException {
	synchronized (threads) {
	    Iterator<Map.Entry<Key, Thread>> i = threads.entrySet().iterator();
	    while (i.hasNext()) {
		Map.Entry<Key, Thread> next = i.next();
		i.remove();
		stopThread(next.getValue(), maxWaitTime);
	    }
	}
    }

}

@@ -647,22 +647,21 @@
 %7B%0A%0A    p
-rivate
+ublic
  static 
@@ -1067,24 +1067,171 @@
 (threads) %7B%0A
+%09    if (threads.containsKey(key)) %7B%0A%09%09throw new IllegalStateException(String.format(%22A job for key %25s already exists.%22, key.toString()));%0A%09    %7D%0A%0A
 %09    String 
@@ -1826,16 +1826,16 @@
 rupt();%0A
-
 %09t.join(
@@ -1847,32 +1847,127 @@
 itTime);%0A    %7D%0A%0A
+    public void stopThreads() throws InterruptedException %7B%0A%09stopThreads(DEFAULT_WAIT);%0A    %7D%0A%0A
     public void 

Raise error in ThreadManager when trying to submit the same job twice