How can I start thread again? - java

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?

Related

Do these nested ExecutorServices make sense in 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();
}

EDIT - Java while loop means events aren't called

So I've updated my code with the help of Cruncher, and now the clicker appears to work better. However whilst the while(pressed) loop is running, no other events are called & so it stays running.
public class Function implements NativeMouseListener {
private Robot robot;
private boolean pressed = false;
private boolean skip = false;
public Function()
{
try {
robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
}
private void repeatMouse()
{
skip = true;
robot.mouseRelease(InputEvent.BUTTON1_MASK);
while (pressed)
{
System.out.println("pressed while loop " + pressed);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void nativeMouseClicked(NativeMouseEvent nativeMouseEvent) {
}
#Override
public void nativeMousePressed(NativeMouseEvent nativeMouseEvent) {
System.out.println("GG");
if (!(nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)) {
System.out.println("Returned.");
return;
}
if (!Native.get().getData().getEnabled())
{
System.out.println("Isn't enabled.");
return;
}
pressed = true;
repeatMouse();
}
#Override
public void nativeMouseReleased(NativeMouseEvent nativeMouseEvent) {
System.out.println("released");
if (!(nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)) {
System.out.println("Returned 2");
return;
}
if (!skip)
{
System.out.println("pressed " + pressed);
pressed = false;
System.out.println("pressed " + pressed);
} else {
skip = false;
}
}
}
Any idea why the while loop would stop events from being called? Do I need to use multi threading or some of that jazz?
Thank you.
For one, your main method is not included in your code, but I assume it contains the following line(or similar):
new Project()
try {
bot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
while (pressed) {
bot.mousePress(InputEvent.BUTTON1_MASK);
//bot.mouseRelease(InputEvent.BUTTON1_MASK);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Now let's look at this code. When this runs, pressed will be false at the beginning(presumably), and it will just exit and not be running on later clicks.
What you want to do is have your loop started when you register a click. Let's move it into another method
private void repeatMouse() {
bot.mouseRelease(InputEvent.BUTTON1_MASK);
while (pressed) {
bot.mousePress(InputEvent.BUTTON1_MASK);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Now let's call it in your mouse down native hook
#Override
public void nativeMousePressed(NativeMouseEvent nativeMouseEvent) {
if (nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)
{
pressed = true;
System.out.println(pressed);
repeatMouse();
}
}
EDIT:
It appears your other problem is that after the first mouseRelease, the handler will get called from the native library. I have a potential solution for this.
First next to where you define your pressed variable, define a new skipRelease
boolean skipRelease = false;
Then before every call to mouseRelease, first set skipRelease to true. Then change your mouseRelease handler to the following
#Override
public void nativeMouseReleased(NativeMouseEvent nativeMouseEvent) {
if (nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)
{
if(skipRelease) {
skipRelease = false;
return;
}
pressed = false;
System.out.println(pressed);
}
}

How to cause a left click then turn off thread?

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(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
public void stop() {
this.running = false;
}
public void start() {
this.running = true;
}
So I have some code someone provided me to monitor the change in color in the middle of the screen. I want to essentially turn on/off checkPixel() after I press something like F9 but how can I do this without a GUI because I can't seem to find anything that allows this. I believe KeyListeners only work with GUIs?
EDIT: Ok so instead while I'm checking for pixel changes in the thread. Once a pixel change has been detected I want to cause create a "left click action" in checkPixel() then turn off the thread. Any help with this?
I guess you want functionality provided by JNativeHook library.
The library allows for grabbing a key from the backgrond.

How to reference button listener in a while loop?

In my Java code I have a while loop as shown below. I want when the end of file is reached or the pause button in the GUI is pressed, the while loop exits. How can I link the button listener from the GUI to the while loop?
Note: in the below code, the this.isPausePressed is a flag inside the pause button listener which is true if the pause button is pressed and false otherwise
code:
while ( ((line = this.logFileBuffer.readLine()) != null) && (!this.isPausePressed) ) {
statusarea.append(Log.d(TAG, "parseTimeStamp", "isPauseButtonPressed: " + this.isPausePressed) + "\n");
String timeStamp = line.split(this.VALUE_SEPARATOR)[0];
Thread timeStampThread = new Thread(new TimeStampTimerThread(++this.markCounter, timeStamp), "TimeStampThread_" + this.markCounter);
timeStampThread.start();
this.setLastFileMarker(this.markCounter);
}
Update_1
i created three threads, each controls one of the GUI buttons with actionListener(play, pause and stop). and inside each respective buttonListener i set the according flags on/off and however the problem still exists.
please see the updated code posted below. the problem is when i click pause, the debugging statement , in onPause() method, always show that the getLastFileMarker() method reached its maximum. wich means, when the pause button is clicked and its flage isPausePressed set to true, the while-loop does not exit.
note:setLastFileMarker() is set inside the wile-loop in the ParseTimeStamp() method. all these methods are posted. kindly have alook at it
createGUI {
this.playButtonThread = new Thread(this.playButtonRunnable, "playButtonThread");
this.pauseButtonThread = new Thread(this.pauseButtonRunnable, "pauseButtonThread");
this.stopButtonThread = new Thread(this.stopButtonRunnable, "stopButtonThread");
this.playButtonThread.start();
this.pauseButtonThread.start();
this.stopButtonThread.start();
}//CreateGui
Runnable playButtonRunnable = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
playButtonListener();
}
};
Runnable pauseButtonRunnable = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
pauseButtonListener();
}
};
Runnable stopButtonRunnable = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
stopButtonListener();
}
};
protected void playButtonListener() {
// TODO Auto-generated method stub
Bplay.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if (isPausePressed) {
isPlayPressed = true;
isPausePressed = false;
continueReading();
}else if (!isPlayPressed) {
isPlayPressed = true;
try {
onPlay();
} catch (IOException
| InterruptedException | MqttException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
protected void pauseButtonListener() {
// TODO Auto-generated method stub
Bpause.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if (isPlayPressed) {
isPlayPressed = false;
isPausePressed = true;
try {
onPause();
} catch (IOException | MqttException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
protected void stopButtonListener() {
// TODO Auto-generated method stub
Bstop.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if (isPlayPressed) {
isStopPressed = true;
try {
onStop();
} catch (MqttException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
protected void continueReading() {
// TODO Auto-generated method stub
}
private void onPause() throws IOException, MqttException {
// TODO Auto-generated method stub
statusarea.append(Log.w(TAG, "onPause", "onPause() is called") + "\n");
if (!this.logFileBuffer.markSupported()) {
statusarea.append(Log.w(TAG, "onPause", "stream does not support .mark() and .reset()
operations.") + "\n");
}else {
this.logFileBuffer.mark(this.getLastFileMarker());
statusarea.append(Log.i(TAG, "onPause", "last mark set in line#: " +
this.getLastFileMarker()) + "\n");
this.timer.cancel();
//this.getClient().disconnect();
}
simulationarea.append(Log.w(TAG, "onPause", "PAUSE") + "\n");
}
ParseTimeStamp method:
while ( ((line = this.logFileBuffer.readLine()) != null) && (!isPausePressed) ) {
statusarea.append(Log.d(TAG, "parseTimeStamp", "isPauseButtonPressed: " +
isPausePressed) + "\n");
String timeStamp = line.split(this.VALUE_SEPARATOR)[0];
Thread timeStampThread = new Thread(new TimeStampTimerThread(++this.markCounter,
timeStamp), "TimeStampThread_" + this.markCounter);
timeStampThread.start();
this.setLastFileMarker(this.markCounter);
}
Update_2:
I deleted the three threads control the GUI buttons as suggested. and just implemented their listeners as shown below. the onPlay() method, shown above in update_1, calls the parseTimeStamp() which has the 'while-loop ', also posted above in update_1.
at run time, when pause button is clicked the while-loop does not exit.
Code
Bplay.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if (isPausePressed) {
isPlayPressed = true;
isPausePressed = false;
continueReading();
}else if (!isPlayPressed) {
isPlayPressed = true;
try {
onPlay();
} catch (IOException
| InterruptedException | MqttException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
Bpause.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if (isPlayPressed) {
isPlayPressed = false;
isPausePressed = true;
try {
onPause();
} catch (IOException | MqttException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
Bstop.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if (isPlayPressed) {
isStopPressed = true;
try {
onStop();
} catch (MqttException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
You only need to set the listener once, some place before the loop is started.
At the moment you click the button, the button's click listener will be fired asynchronously (i.e. from another thread as your loop code, a.k.a. the event dispatch thread). So the loop will suddenly "see" the changed value for isPausePressed and quit, just like that.
This implies that you should not do these kind of loops from inside the "event dispatch thread" as this would prevent loop and event to happen in parallel. See this document (and sub-documents) for more info on the "event dispatch thread" and concurrency in Swing in general.
update:
For an example, see below. Note that there's no need for any thread creation or other strange stuff. Swing automatically starts the notorious Event Dispatch Thread for you, and all event related code will automatically run inside that thread. This way, your main loop code will happily run in parallel with the actionListener's actionPerformed method (as soon as you click the button). So the isPausePressed flag will change seemingly during execution of your While loop. It's really that simple.
private boolean isPausePressed = false;
JButton b = new JButton("Pause!");
b.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
isPausePressed = true;
}
});
// ....
while (!isPausePressed)
{
// do some work
}

Android - change background resource twice with pause between

I am trying to set a button to green for 1 second, then back to red. But It won't change to green anymore, if I comment out the "change to red" part, it will turn green fine. I have used Log.d and it shows that there is a second difference between changing from "change to green" to "change to red" so you should see the green before the red, but for some reason this is not working.
Any Ideas?
public void level1() throws InterruptedException {
int Low = 1000;
int High = 3000;
int t = r.nextInt(High-Low) + Low;
Thread.sleep(t);
handleTime.post(new Runnable() {
#Override
public void run() {
int i = r.nextInt(5);
switch(i) {
case 1:
try {
setGreen(tLeft);
tLActive = true;
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
tLActive = false;
setRed(tLeft);
}
break;
case 2:
try {
setGreen(tRight);
tRActive = true;
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
tRActive = false;
setRed(tRight);
}
break;
case 3:
try {
setGreen(center);
cActive = true;
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
cActive = false;
setRed(center);
}
break;
case 4:
try {
setGreen(bLeft);
bLActive = true;
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
bLActive = false;
setRed(bLeft);
}
break;
case 5:
try {
setGreen(bRight);
bRActive = true;
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
bRActive = false;
setRed(bRight);
}
break;
}
}
});
}
private void setGreen(ImageButton b) {
b.setBackgroundResource(R.drawable.green);
Log.d("green", "green");
}
private void setRed(ImageButton b) {
b.setBackgroundResource(R.drawable.red);
Log.d("red", "red");
}
You able to use Handler.class
As simple example:
setGreenColor();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
setRedColor();
}
}, 1000);
where postDelayed will be called in UI thread.
The Runnable in this case runs on the UI thread. The same thread responsible for drawing. But drawing is not immediate instead the UI element gets invalidated because it wants to be redraw and when the UI thread has time it will preform the redraw.
{ //the essence of the runnable code
setGreen(bRight); //UI element is invalidated, it wants to be redrawn green
Thread.sleep(1000); //UI thread is tied up here (blocked) so nothing can happen on UI
setRed(bRight); //UI element is invalidated again, it wants to be redrawn red now
// replacing the green before it's even been seen
} //end of runnable code
//now the redrawing occurs, and it will only be red.
As Eldar Mensutov points out one solution is to post another runnable with a delay. That way the UI thread will not be blocked by the Thread.sleep.

Categories