0
\$\begingroup\$

This code is executed on a background service every 60 seconds on an Android app. Each class instantiated on FutureTask (WifiInfoFetch and WifiApResults) contains an insert to an SQLite database. We changed the original implementation (without a FutureTask) as we think the first insert was still locking the database when the second one tried to do its insert as they were executed very close to each other.

I think that with the code below, the second thread should wait until the first one is finished to start. Is this true? Also, what happens if for any reason thread 1 does not finish? Is there a way to set a timeout to interrupt it?

WifiInfo wifi = wifiManager.getConnectionInfo();
if (wifi == null) return;

WifiInfoFetch wifiInfo = new WifiInfoFetch(getApplicationContext(), wifi);
WifiApResults scanResults = new WifiApResults(getApplicationContext(), wifiManager.getScanResults());

FutureTask<String> futureWifiInfo = new FutureTask<>(wifiInfo);
FutureTask<String> futureScanResults = new FutureTask<>(scanResults);

ExecutorService executor = Executors.newFixedThreadPool(2);
try {
    executor.submit(futureWifiInfo).get();
    executor.submit(futureScanResults);
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}

Thanks!

\$\endgroup\$
1
  • \$\begingroup\$ Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers. \$\endgroup\$
    – Vogel612
    Commented Jan 26, 2017 at 15:21

2 Answers 2

2
\$\begingroup\$

There is no need for the FutureTask, the executor service will create a future that you can use to wait on the task and get the result (if any).

executor.submit(futureWifiInfo).get();

This is basically the same as just calling futureWifiInfo.run(); (or call) In other words you aren't quite there yet with making this properly asynchronous.

It does let you set a timeout on the get simply by adding the timeout parameters:

Future<String> futureWifiInfo = executor.submit(wifiInfo);
try {
    futureWifiInfo.get(1, TimeUnit.SECONDS);
    executor.submit(scanResults);

} catch (TimeoutException e) {
    // get timed out -> cancel it
    futureWifiInfo.cancel(true);

} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}
\$\endgroup\$
3
  • \$\begingroup\$ Thanks!. According to the docs if cancel() is called when the task never started that task will be never be executed. What are the reasons a task could not be started in this case? \$\endgroup\$
    – Julio
    Commented Jan 25, 2017 at 18:52
  • \$\begingroup\$ if the task is (still) running when cancel is called with true as parameter then the thread will get its interruped flag set which the code inside the callable can check with Thread.interrupted() (it also makes a blocking function throw InterrupedException) so the call can return with a failure. \$\endgroup\$ Commented Jan 25, 2017 at 19:31
  • \$\begingroup\$ The first thread is not executing, see my edit above \$\endgroup\$
    – Julio
    Commented Jan 25, 2017 at 20:26
0
\$\begingroup\$

I modified my original answer adding the shutdown() method for GC and also an awaitTermination since this code is being executed in an IntentService and that could kill the threads when its execution is over.

                WifiInfoFetch wifiInfo = new WifiInfoFetch(getApplicationContext(), wifi);
                WifiApResults scanResults = new WifiApResults(getApplicationContext(), wifiManager.getScanResults());

                ExecutorService executor = Executors.newSingleThreadExecutor();
                executor.submit(wifiInfo);
                executor.submit(scanResults);
                executor.shutdown();

                try {
                    executor.awaitTermination(1000, TimeUnit.MILLISECONDS);
                } catch (InterruptedException e) {
                    Log.d(TAG, "WiFi data recording was interrupted because took more than 1000 ms");
                }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.