Do these nested ExecutorServices make sense in Java? - java

I stumbled across some legacy code and found this expression in connection with some async database handling:
ExecutorService SERVICE = Executors.newCachedThreadPool();
SERVICE.execute(() - > {
try {
SERVICE.execute(new Runnable() {
#Override
public void run() {
// do stuff
}
});
} catch (Exception e) {
e.printStackTrace();
}
});
My question is, is there any reason for calling execute() twice on the ExecutorService? Wouldn't it be easier to just run:
try {
SERVICE.execute(new Runnable() {
#Override
public void run() {
// do stuff
}
});
} catch (Exception e) {
e.printStackTrace();
}

Related

JavaSwing Update button based on Network Connection flag

I have a Java swing UI where I need to disable a button on the UI if I could not detect an active internet connection.
The code function properly so far, but when I get disconnected from the internet, it does not retrigger the method to update the boolean flag.
How can I add an event on that flag to let my button consume it during the lifetime of the application?
public class Main {
private static JButton button;
private static boolean testButtonEnabled;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
/*
* function that returns true/false if connected to the internet
*/
if(Utils.isConnectedToInternet()) {
logger.debug("System is connected to the internet");
testButtonEnabled=true;
} else {
logger.debug("System is not connected to the internet");
testButtonEnabled=false;
}
Main window = new Main();
window.frame.setVisible(true);
button = new JButton("my button");
/*
* set the internet status
*/
button.setVisible(testButtonEnabled);
}
}
}
}
Again, this code:
SwingWorker<Void, String> worker = new SwingWorker<Void, String>()
{
public Void doInBackground()
{
while(true)
{
try {
isConnectedToInternet = Utils.isConnectedToInternet();
if (isConnectedToInternet) {
btn_online2.setEnabled(isConnectedToInternet);
} else {
btn_online2.setEnabled(isConnectedToInternet);
}
logger.debug("Internet connection status: " + isConnectedToInternet);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
worker.execute();
is dangerous since it makes mutational changes to a Swing component from a background thread. While this code may work 95% of the time, it can fail in unpredicatable ways and at unpredicatable times. Better to only mutate Swing components on the event thread. For instance, even this would be better:
SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {
#Override
public Void doInBackground() {
while(true) {
try {
isConnectedToInternet = Utils.isConnectedToInternet();
// note that there is no need for the if/else block
SwingUtilities.invokeLater(() -> {
btn_online2.setEnabled(isConnectedToInternet);
});
logger.debug("Internet connection status: " + isConnectedToInternet);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
worker.execute();
or better still, using SwingWorker's publish/process:
SwingWorker<Void, Boolean> worker = new SwingWorker<Void, Boolean>() {
#Override
public Void doInBackground() {
while(true) {
try {
isConnectedToInternet = Utils.isConnectedToInternet();
// note that there is no need for the if/else block
publish(Utils.isConnectedToInternet());
logger.debug("Internet connection status: " + isConnectedToInternet);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
protected void process(List<Boolean> chunks) {
for (Boolean chunk : chunks) {
btn_online2.setEnabled(chunk);
}
}
};
worker.execute();
I was able to resolve using the following method in the initialize() of the frame.
Adding that change part of the swingworker allowed the button to check the flag and assign it to itself whenever it changes.
Now whenever the internet is disconnected the button is disabled and whenever connected the button is enabled.
SwingWorker<Void, String> worker = new SwingWorker<Void, String>()
{
public Void doInBackground()
{
while(true)
{
try {
isConnectedToInternet = Utils.isConnectedToInternet();
if (isConnectedToInternet) {
btn_online2.setEnabled(isConnectedToInternet);
} else {
btn_online2.setEnabled(isConnectedToInternet);
}
logger.debug("Internet connection status: " + isConnectedToInternet);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
worker.execute();

runOnUi slows down the app and make it forced close

i am generating a random string for infinite time and setting it to a EditText.
when i was not using runOnUi app was working on newer devices which have high capability. but it crashes on older model when i start the thread and gave error(called from wrong thread exception)
Then i used runOnUi but it makes the super slow and force close it.
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
tryPass.setText(getAlphaNumericString());
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
});
thread.start();
You're trying to block UI thread by calling Thread.sleep(2000); on UI thread.
Try this way:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
runOnUiThread(new Runnable() {
#Override
public void run() {
tryPass.setText(getAlphaNumericString());
}
});
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();

How can I start thread again?

I know time and time again people have asked how to start a thread after it's been stopped and everyone says you can't. This isn't a duplicate to that because I've found no solution for the problem.
private void runInBackground() {
new Thread(new Runnable() {
#Override
public void run() {
while (running) {
try {
checkPixel();
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
#Override
public void nativeKeyPressed(NativeKeyEvent e) {
// TODO Auto-generated method stub
System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
if(NativeKeyEvent.getKeyText(e.getKeyCode()).equals("F9")){
stop();
}
else if(NativeKeyEvent.getKeyText(e.getKeyCode()).equals("F10")){
}
So in my code I'm listening for global key events using JNativeHook. I can successfully stop the checkPixels() using the F9 key but I'm not understanding what I should do using F10 when I wanna start up checkPixel() again.
checkPixel() basically checks for a change in pixel color
ANSWERED Added an if statement for my state variable running and keep the while loop true allows me to turn on/off the method while keeping the thread open. Thank you Jaboyc
private void runInBackground() {
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
if(running){
try {
checkPixel();
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
Would this work
while (true) {
if (running) {
doStuff();
}
}
in the run method?

How to correctly block Eclipse job

I am using org.eclipse.core.runtime.jobs.JOB to execute backgrounds task that also gathers data from UI controls.
I want to "block" until job is finished (the trigger for the JOB is some ui button event)
Job job = new Job("Job") {
protected IStatus run(IProgressMonitor arg0) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
System.out.println(i);
}
}
});
return Status.OK_STATUS;
}
};
job.schedule();
job.join(); //<-- Doesn't block!!!
if (job.getResult().isOK())
System.out.println("success"); //<-- Result is ok!!
else
System.out.println("failed");

JavaFX : Use a Thread more than once

I'm new with JavaFX and I've a little problem with a thread: I can execute it twice and I can't find why.
Here is a sum-upt of my code:
Task<Void> task = new Task<Void>() {
#Override public Void call() throws ImageLoadedException, HomographyException, IOException {
try{
System.out.println("GO !");
return null;
}
catch (Exception e){
e.printStackTrace();
}
return null;
}
#Override
protected void succeeded() {
super.succeeded();
System.out.println("SUCCEEDED");
}
};
#FXML protected void launch(ActionEvent event){
new Thread(task).start();
}
When I click a first time the button who start my thread, my task run without any problem (my console display "GO !" and "SUCCEEDED").
But if I click a second time, nothing append. Am I doing something wrong ? Can't we use a thread more than once ?
From the Thread.start() documentation : No
It is never legal to start a thread more than once. In particular, a
thread may not be restarted once it has completed execution.
From the Concurrency in JavaFX tutorial :
The Task class defines a one-time object that cannot be reused. If you
need a reusable Worker object, use the Service class.
So, you have to consider the Service class rather than Task.
Edit: this should work for you:
Service service = new Service<>(task);
//Updated use this to create a new Service object instead
Service service = new Service() {
#Override
protected Task createTask() {
return new Task() {
#Override
protected Void call() throws Exception {
//Your codes here
return null;
}
};
}
};
#FXML protected void launch(ActionEvent event){
if (!service.isRunning()) {
service.reset();
service.start();
}
}
With a button can fire new tasks
Button btn = new Button();
btn.setText("New task");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Executor ex=new Executor("Task"+count);
ex.start();
count++;
System.out.println("Task Starting...");
}
});
Do it with a wraper class
import java.io.IOException;
import javafx.concurrent.Task;
public class Executor {
private String name;
private Task<Void> task;
public Executor(final String name) {
this.name=name;
task = new Task<Void>() {
#Override
public Void call() throws IOException, InterruptedException {
try {
int i=0;
while(i<20){
System.out.println(name);
Thread.sleep(2000);
i++;
}
return null;
} catch (IllegalThreadStateException e) {
System.out.println(e);
}
return null;
}
#Override
protected void succeeded() {
super.succeeded();
try {
System.out.println(name+" finish");
} catch (Exception ex) {
System.out.println(ex);
}
}
};
}
public void start() {
try {
Thread th = new Thread(task);
th.start();
} catch (Exception ex) {
System.out.println(ex);
}
}
}

Categories