ThreadUtil.java

1
/*******************************************************************************
2
 * Copyhacked (H) 2012-2020.
3
 * This program and the accompanying materials
4
 * are made available under no term at all, use it like
5
 * you want, but share and discuss about it
6
 * every time possible with every body.
7
 * 
8
 * Contributors:
9
 *      ron190 at ymail dot com - initial implementation
10
 ******************************************************************************/
11
package com.jsql.util;
12
13
import com.jsql.model.InjectionModel;
14
import com.jsql.model.bean.database.AbstractElementDatabase;
15
import com.jsql.model.suspendable.AbstractSuspendable;
16
import com.jsql.model.suspendable.callable.ThreadFactoryCallable;
17
import org.apache.logging.log4j.LogManager;
18
import org.apache.logging.log4j.Logger;
19
20
import java.util.HashMap;
21
import java.util.Map;
22
import java.util.concurrent.ConcurrentHashMap;
23
import java.util.concurrent.ExecutorService;
24
import java.util.concurrent.Executors;
25
import java.util.concurrent.TimeUnit;
26
27
/**
28
 * Utility class managing running threads on which the user can act.
29
 * It must be noted that as SwingWorker class are used then only 10 jobs can be run
30
 * at the same time, the 11th will be waiting in the thread pool until one of the 10
31
 * actives one is freed.
32
 */
33
public final class ThreadUtil {
34
    
35
    /**
36
     * Log4j logger sent to view.
37
     */
38
    private static final Logger LOGGER = LogManager.getRootLogger();
39
    
40
    /**
41
     * List of running jobs associated to a database injection task.
42
     * We can interact with those tasks in order to pause/resume and stop the process.
43
     */
44
    // Fix #8258: ConcurrentModificationException on java.util.HashMap$ValueIterator.next()
45
    private final Map<AbstractElementDatabase, AbstractSuspendable> suspendables = new ConcurrentHashMap<>(new HashMap<>());
46
47
    private final InjectionModel injectionModel;
48
    
49
    public ThreadUtil(InjectionModel injectionModel) {
50
        this.injectionModel = injectionModel;
51
    }
52
53
    /**
54
     * Add a job to the list of ongoing tasks. It is used to allow the user to act
55
     * on the job and stop/pause a running process.
56
     * @param elementDatabase component associated to the active job
57
     * @param suspendable active job to act on
58
     */
59
    public void put(AbstractElementDatabase elementDatabase, AbstractSuspendable suspendable) {
60
        this.suspendables.put(elementDatabase, suspendable);
61
    }
62
    
63
    /**
64
     * Get the task associated to the database component.
65
     * It's usually done to act on the task like stop/pause the corresponding process, or
66
     * to check the status of the job.
67
     * @param elementDatabase component associated to the active job
68
     * @return job currently running
69
     */
70
    public AbstractSuspendable get(AbstractElementDatabase elementDatabase) {
71 1 1. get : replaced return value with null for com/jsql/util/ThreadUtil::get → NO_COVERAGE
        return this.suspendables.get(elementDatabase);
72
    }
73
    
74
    /**
75
     * Remove the thread corresponding to the component in order to be
76
     * garbage collected. The thread should be stopped prior the deletion.
77
     * @param elementDatabase component associated to thread
78
     */
79
    public void remove(AbstractElementDatabase elementDatabase) {
80
        this.suspendables.remove(elementDatabase);
81
    }
82
    
83
    /**
84
     * Force to stop every threads still running and empty the list where
85
     * they were instantiated in order to be garbage collected.
86
     */
87
    public void reset() {
88
        
89 1 1. reset : removed call to java/util/Collection::forEach → NO_COVERAGE
        this.suspendables.values().forEach(AbstractSuspendable::stop);
90 1 1. reset : removed call to java/util/Map::clear → NO_COVERAGE
        this.suspendables.clear();
91
    }
92
    
93
    public ExecutorService getExecutor(String nameThread) {
94
95
        ExecutorService taskExecutor;
96
        
97 1 1. getExecutor : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isLimitingThreads()) {
98
            
99
            int countThreads = this.injectionModel.getMediatorUtils().getPreferencesUtil().countLimitingThreads();
100
            taskExecutor = Executors.newFixedThreadPool(countThreads, new ThreadFactoryCallable(nameThread));
101
            
102
        } else {
103
            taskExecutor = Executors.newCachedThreadPool(new ThreadFactoryCallable(nameThread));
104
        }
105
        
106 1 1. getExecutor : replaced return value with null for com/jsql/util/ThreadUtil::getExecutor → NO_COVERAGE
        return taskExecutor;
107
    }
108
109
    public void shutdown(ExecutorService taskExecutor) {
110
111
        int timeout = 15;
112 1 1. shutdown : negated conditional → NO_COVERAGE
        if (this.injectionModel.getMediatorUtils().getPreferencesUtil().isConnectionTimeout()) {
113
            timeout = this.injectionModel.getMediatorUtils().getPreferencesUtil().countConnectionTimeout();
114
        }
115
116
        try {
117 1 1. shutdown : removed call to java/util/concurrent/ExecutorService::shutdown → NO_COVERAGE
            taskExecutor.shutdown();
118 1 1. shutdown : negated conditional → NO_COVERAGE
            if (!taskExecutor.awaitTermination(timeout, TimeUnit.SECONDS)) {
119
                taskExecutor.shutdownNow();
120
            }
121
        } catch (InterruptedException e) {
122
123
            LOGGER.log(LogLevelUtil.IGNORE, e, e);
124 1 1. shutdown : removed call to java/lang/Thread::interrupt → NO_COVERAGE
            Thread.currentThread().interrupt();
125
        }
126
    }
127
}

Mutations

71

1.1
Location : get
Killed by : none
replaced return value with null for com/jsql/util/ThreadUtil::get → NO_COVERAGE

89

1.1
Location : reset
Killed by : none
removed call to java/util/Collection::forEach → NO_COVERAGE

90

1.1
Location : reset
Killed by : none
removed call to java/util/Map::clear → NO_COVERAGE

97

1.1
Location : getExecutor
Killed by : none
negated conditional → NO_COVERAGE

106

1.1
Location : getExecutor
Killed by : none
replaced return value with null for com/jsql/util/ThreadUtil::getExecutor → NO_COVERAGE

112

1.1
Location : shutdown
Killed by : none
negated conditional → NO_COVERAGE

117

1.1
Location : shutdown
Killed by : none
removed call to java/util/concurrent/ExecutorService::shutdown → NO_COVERAGE

118

1.1
Location : shutdown
Killed by : none
negated conditional → NO_COVERAGE

124

1.1
Location : shutdown
Killed by : none
removed call to java/lang/Thread::interrupt → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.16.1