So basically i tried to get this while loop to run inside this thread, it should activate when "activate" evaluates to true but for some reason it is not working.
"activate" is boolean value which activates when user presses mouse button (i setted up listener for that). If anyone wonders im using jnativehook library for this project. Any help or explanation would be greatly appreciated.
private boolean activate;
private Robot robot;
#Override
public void run() {
try {
robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
while(true) {
if (activate == true) {
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
robot.delay(100);
}
}
}
activate is never set to true.
If you don't believe me then add this line at the bottom of your while loop:
System.out.println("activate = " + activate);
One possibility is that the compiler (either the Java compiler, or the JIT compiler) has decided that it does not need to test activate because it can prove that nothing inside the while loop ever changes it. In most compiled programming languages, the compiler is allowed to assume that the code will be single threaded unless you do something special to tell it otherwise. That assumption is justified because it enables the compiler to generate much more efficient code most of the time.
Accessing the variable from within a synchronized block, or declaring the variable to be volatile would prevent the compiler from making that assumption.
Better still would be to use a private final AtomicBoolean activate;.
// Here is the sample program which should run your method correctly. All the changes
// are commented upon. Don't judge harshly, not a professional with java
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.util.Scanner;
class Processor extends Thread {
// Have to initialize the variable here
private boolean activate = true;
private Robot robot;
public void run() {
try {
robot = new Robot();
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// No need for while (true) here
while (activate) {
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
robot.delay(100);
}
}
// method to stop the program
public void shutdown() {
activate = false;
}
}
public class App {
public static void main(String[] args) throws AWTException, InterruptedException, NullPointerException {
// activates the process
Processor p = new Processor();
p.start();
// Press any key to stop the process
// program will run endlessly until scanner value (key input) is provided
Scanner key_input = new Scanner(System.in);
key_input.nextLine();
p.shutdown();
}
}
Thanks for all suggestion fixed the problem by passing class instance to my MouseListener class.
For anyone that gets same problem:
public boolean activate;
public boolean toggled;
private Robot robot;
public MouseListener mouseListener = new MouseListener();
public KeyboardListener keyListener = new KeyboardListener();
public static Game instance;
public Game() {
this.activate = false;
// this.toggled = false;
try {
GlobalScreen.registerNativeHook();
GlobalScreen.isNativeHookRegistered();
GlobalScreen.addNativeMouseListener(mouseListener);
GlobalScreen.addNativeKeyListener(keyListener);
} catch (NativeHookException e) {
e.printStackTrace();
}
}
public void run() {
try {
robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
while(true) {
try {
Thread.sleep(1L);
if(Game.this.isActivate()) {
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.delay(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public boolean isActivate() {
return activate;
}
public void setActivate(boolean activate) {
this.activate = activate;
}
public boolean isToggled() {
return toggled;
}
public void setToggled(boolean toggled) {
this.toggled = toggled;
}
**public static Game getGame() {
if(Game.instance == null) {
Game.instance = new Game();
}
return Game.instance;
}**
Here is the class that changes "activate" to "true".
public void nativeMouseClicked(NativeMouseEvent e) {
// nothing
}
public void nativeMousePressed(NativeMouseEvent e) {
if(e.getButton() == NativeMouseEvent.BUTTON1) {
Game.getGame().setActivate(true);
}
}
public void nativeMouseReleased(NativeMouseEvent e) {
if(e.getButton() == NativeMouseEvent.BUTTON1) {
Game.getGame().setActivate(false);
}
}
}
Related
I'm having some trouble with Jline and not quite understanding how to work it properly, everything seems to work from the examples but when i attempt to move it into my console application things go weird.
I've come across two issues:
When you write input into the console while something else is logging a message via System out, the written input gets broken. (View: https://i.imgur.com/ZAJDjTI.png)
I attempted to sync the commands to the main thread since the reader thread will be blocking, but this time you'll find that this causes the output text to take over the commands input space.
((Green text is the input, white is output)View: https://i.imgur.com/CdKiIYy.png)
The output i expected was for input coming from the bottom of the console to be unaffected by the output of the console, leaving a smooth input text layer at the bottom. (View: https://i.imgur.com/HfH5l8U.png?1)
Here's an example class i wrote to demonstrate the two problems I'm having:
import jline.console.ConsoleReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.locks.ReentrantLock;
public class Example {
private ConsoleReader consoleReader;
private LinkedList<Runnable> syncQueue = new LinkedList<>();
private ReentrantLock lock = new ReentrantLock();
public Example() {
try {
this.consoleReader = new ConsoleReader();
this.consoleReader.setExpandEvents(false);
} catch (IOException e) {
e.printStackTrace();
}
//If you enable this, Jline seems to be disrupted by the System out.
// startStopwatch();
setupJline();
//Ticker, its ugly i know
while (true) {
lock.lock();
try {
while (syncQueue.size() > 0) {
Runnable runnable = syncQueue.poll();
try {
runnable.run();
} catch (Exception e) {
e.printStackTrace();
}
}
} finally {
lock.unlock();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void setupJline() {
new Thread("Console Thread") {
#Override
public void run() {
while (true) {
try {
String line = consoleReader.readLine(">");
if (line != null && line.trim().length() > 0) {
//Lets pass this on as an instruction to our program
//Sync seems okay, output wise
handleInstructionSynced(line);
//async seems to mess things up though, comment the handleInstructionSynced method and
//uncomment the Async one to see what i mean.
//handleInstructionAsync(line);
}
consoleReader.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start();
}
//Just a dummy example instruction handler
private void handleInstructionAsync(String input) {
System.out.println("You've input \"" + input + "\" as your instruction.");
}
private void handleInstructionSynced(String input) {
runSync(() -> System.out.println("You've input \"" + input + "\" as your instruction."));
}
private void runSync(Runnable runnable) {
lock.lock();
try {
syncQueue.add(runnable);
} finally {
lock.unlock();
}
}
private void startStopwatch() {
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
int time = 0;
#Override
public void run() {
System.out.println(time + " seconds counted");
time++;
}
};
timer.scheduleAtFixedRate(timerTask, 0, 1000);
}
public static void main(String[] args) {
new Example();
}
}
Any solutions?
I have looked at a bunch of answers to a previous question I had (it was answered), but something that I kept seeing were methods like:
public void keyPressed(KeyEvent e)
but none ever showed where these methods were used, so I never figured out what to do with the argument.
Example:
public void keyPressed(KeyEvent e, Robot r) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_W) {
r.keyPress(KeyEvent.VK_R);
r.mousePress(InputEvent.BUTTON1_MASK);
try { Thread.sleep(100); } catch (Exception s) {}
r.mouseRelease(InputEvent.BUTTON1_MASK);
}
}
public static void autoCliker() throws AWTException, InterruptedException
{
Robot r = new Robot();
while(KeyPressed(not sure what to do here, r)//this is what my question is about
{
Thread.sleep(10);
r.keyPress(KeyEvent.VK_R);
r.mousePress(InputEvent.BUTTON1_MASK);
try { Thread.sleep(100); } catch (Exception e) {}
r.mouseRelease(InputEvent.BUTTON1_MASK);
}
}
It's more about how to use an Event in an argument within a method than about the KeyEvent, I am just using one of my programs as an example.
This method, along with others, shows up when your class implements KeyListener.
public class Test implements KeyListener {
This method senses key's pressed on the keyboard. If you want to detect a certain key like w. Do this:
if(e.getKeyCode.equals(KeyEvent.VK_W);
Hope this helps.
I have a piece of Java program that essentially does the following:
public static void main(String[] args)
{
while(true)
{
// does stuff ...
}
}
The infinite loop is there by design - when left alone the program will loop infinitely. For the most part it works fine. However, sometimes I want to take the program down for maintenance, and when I take it down I want to make sure that it runs through all the code in the loop to the end then exit.
I am wondering what is the best solution for this. One idea I have in mind is to do something like this:
public static void main(String[] args)
{
File f = new File("C:\exit.txt");
while(!f.exists())
{
// does stuff ...
}
}
which basically allows me to gracefully get out of the loop by creating a file called "exit.txt". This is probably OK for my purposes, but I would like to know if there are better, alternative methods.
I think that the WatchService that was introduced in Java 7 may be of use here (if you prefer a file based approach that is). From the JavaDocs:
A watch service that watches registered objects for changes and events. For example a file manager may use a watch service to monitor a directory for changes so that it can update its display of the list of files when files are created or deleted.
Basically what this means is that you can set up a WatchService that can watch a folder for changes. When a change occurs you can choose what actions to take.
The following code uses the WatchService to monitor a specified folder for changes. When a change has happened it executes a Runnable that the caller has provided (the method runWhenItIsTimeToExit).
public class ExitChecker {
private final Path dir;
private final Executor executor;
private final WatchService watcher;
// Create the checker using the provided path but with some defaults for
// executor and watch service
public ExitChecker(final Path dir) throws IOException {
this(dir, FileSystems.getDefault().newWatchService(), Executors.newFixedThreadPool(1));
}
// Create the checker using the provided path, watcher and executor
public ExitChecker(final Path dir, final WatchService watcher, final Executor executor) {
this.dir = dir;
this.watcher = watcher;
this.executor = executor;
}
// Wait for the folder to be modified, then invoke the provided runnable
public void runWhenItIsTimeToExit(final Runnable action) throws IOException {
// Listen on events in the provided folder
dir.register(watcher,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY);
// Run it async, otherwise the caller thread will be blocked
CompletableFuture.runAsync(() -> {
try {
watcher.take();
} catch (InterruptedException e) {
// Ok, we got interrupted
}
}, executor).thenRunAsync(action);
}
}
So, how do we use the checker then? Well, the following code illustrates this:
public static void main(String... args) throws IOException, InterruptedException {
// Setup dirs in the home folder
final Path directory = Files.createDirectories(
new File(System.getProperty("user.home") + "/.exittst").toPath());
// In this case we use an AtomicBoolean to hold the "exit-status"
AtomicBoolean shouldExit = new AtomicBoolean(false);
// Start the exit checker, provide a Runnable that will be executed
// when it is time to exit the program
new ExitChecker(directory).runWhenItIsTimeToExit(() -> {
// This is where your exit code will end up. In this case we
// simply change the value of the AtomicBoolean
shouldExit.set(true);
});
// Start processing
while (!shouldExit.get()) {
System.out.println("Do something in loop");
Thread.sleep(1000);
}
System.out.println("Exiting");
}
Finally, how do you exit the program then? Well simply touch a file in the specified folder. Example:
cd ~/.exittst
touch exit-now.please
Resources:
A good tutorial on how to use the WatchService
WatchService JavaDocs
A good article about CompletableFuture
More stuff about CompletableFuture
Why the WatchService is slow on Mac OS X
One could employ some sophisticated techniques here. The file watchdog is one option. RMI could be another. But in fact, the mechanisms that are required here are quite simple, so I'd like to propose another (very simple) solution.
Note: This solution is just one option, showing that it is possible to do it that way. It is not a general recommendation, and whether it is "good" or not depends on the application case.
The solution is simply based on Sockets. The ServerSocket#accept method already encapsulates the functionality that you want:
Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made.
Based on this, it is trivial to create such a "remote control": The server just waits for a connection, and sets a flag when the connection is opened:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.atomic.AtomicBoolean;
class RemoteExitServer
{
private final AtomicBoolean flag = new AtomicBoolean();
RemoteExitServer()
{
Thread t = new Thread(new Runnable()
{
#Override
public void run()
{
waitForConnection();
}
});
t.setDaemon(true);
t.start();
}
private void waitForConnection()
{
ServerSocket server = null;
Socket socket = null;
try
{
server = new ServerSocket(1234);
socket = server.accept();
flag.set(true);
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (server != null)
{
try
{
server.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
if (socket != null)
{
try
{
socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
boolean shouldExit()
{
return flag.get();
}
}
The client does exactly that: It opens a connection, and nothing else
import java.io.IOException;
import java.net.Socket;
public class RemoteExitClient
{
public static void main(String[] args)
{
Socket socket = null;
try
{
socket = new Socket("localhost", 1234);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (socket != null)
{
try
{
socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
The application is then also very simple:
public class RemoteExitTest
{
public static void main(String[] args)
{
RemoteExitServer e = new RemoteExitServer();
while (!e.shouldExit())
{
System.out.println("Working...");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
System.out.println("done");
}
}
(The code could be made even more concise with try-with-resources, but this should not matter here)
You could make use of runtime shutdown hook. That way you won't need to use console input in order to stop the loop. If JVM is being closed normally then shutdown hook thread will run. This thread will wait for the end of current loop iteration. Keep in mind that there are some limitations when using hooks though: https://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#addShutdownHook-java.lang.Thread-
import java.util.concurrent.CountDownLatch;
public class Test {
private volatile static CountDownLatch lastIterationLatch = null;
private static boolean stop = false;
public static void main(String [] args) throws Exception {
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
lastIterationLatch = new CountDownLatch(1);
try {
lastIterationLatch.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
while(!stop) {
System.out.println("iteration start");
Thread.sleep(200);
System.out.println("processing...");
Thread.sleep(200);
System.out.println("processing...");
Thread.sleep(200);
System.out.println("processing...");
Thread.sleep(200);
System.out.println("iteration end");
if(lastIterationLatch != null) {
stop = true;
lastIterationLatch.countDown();
}
}
}
}
For something quick/dirty, use Signals:
boolean done = false;
// ...
Signal.handle(new Signal("USR1"), new SignalHandler() {
#Override
public void handle(Signal signal) {
// signal triggered ...
done = true;
}
});
// ...
while(!done) { ... }
Then, use kill -USR1 _pid_ to trigger the signal.
You could use a AtomicBoolean as in the test program below.
To suspend just type true into the console to resume type false. The program will never exit.
public class Test2 {
public static void main(String[] args) {
final AtomicBoolean suspended = new AtomicBoolean(false);
new Thread() {
public void run() {
while (true)
{
Scanner sc = new Scanner(System.in);
boolean b = sc.nextBoolean();
suspended.set(b);
}
}
}.start();
while(true){
if(!suspended.get()){
System.out.println("working");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else{
//System.exit(0) //if you want to exit rather than suspend uncomment.
}
}
}
}
I'm trying to stop a java thread from a different class, but unable to figure out. I have looked into the below links, googled a lot from past 2 days but unable to nail down. May be a simple thing which i need to change but i'm out of options and hence posting it here.
Referred Links
java external threads (outside the class file it's used)
http://tutorials.jenkov.com/java-concurrency/creating-and-starting-threads.html
http://www.java2novice.com/java_thread_examples/
While typing the question, I referred the below links as well..
Stop a thread from outside
Below is my code sample. I'm able to start the WorkerThread from the MainThread and get into the loop. But unable to stop the thread started using the StopThread class.
I've also used the volatile option suggested in the below link.
http://tutorials.jenkov.com/java-concurrency/volatile.html
I feel I'm making a simple mistake, but not able to identify it.
//class WorkerThread
package main;
public class WorkerThread implements Runnable
{
public WorkerThread() {
isRunning = true;
}
public WorkerThread(boolean False) {
isRunning = False;
}
private volatile boolean isRunning;
public synchronized void stopThread() {
isRunning = false;
}
public synchronized boolean IsThreadRunning() {
return isRunning;
}
#Override
public void run()
{
int i = 1;
while(isRunning)
{
System.out.println("Loop " + i);
i++;
try { Thread.sleep(2000); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
//class MainThread
package main;
public class MainThread
{
public static Thread t;
public static void main(String[] args)
{
t = new Thread(new WorkerThread());
t.start();
}
}
//class StopThread
package main;
public class StopThread
{
public static void main(String[] args)
{
//What should i write here to stop the thread started by MainThread
MainThread.t.interrupt();
}
}
public class MainThread
{
public static Thread t;
public static void main(String[] args)
{
t = new Thread(new WorkerThread());
t.start();
}
}
public class StopThread
{
public static void main(String[] args)
{
MainThread.t.interrupt();
}
}
It is not safe to call Thread.stop() it is listed as deprecated in JavaDocs
Also this may be just for the sake of this question, but why does your program have two main methods?
You have an opportunity to make use of what you defined volatile variable and gracefully come out of thread like below:
public class MainThread
{
public static WorkerThread workerThread;
public static void main(String[] args)
{
workerThread = new WorkerThread();
Thread t = new Thread(workerThread);
t.start();
}
}
public class StopThread
{
public static void main(String[] args)
{
Main.workerThread.stopThread();
}
}
Note: This solution works but not a perfect solution.
You can write and read value of isRunning variable from a properties file. This way you can have interaction between two different java processes. ThreadWorker just creates file upon initiation & and just makes attempt to read the file after that. StopThread modifies the properties file when triggered which should be picked up by ThreadWorker.
Check below example:
public class ThreadWorker implements Runnable
{
public volatile static boolean isRunning = false;
public ThreadWorker() {
Properties p = new Properties();
p.setProperty("isRunning", "1");
FileOutputStream out;
try {
//Writes all properties in appProperties file
out = new FileOutputStream("appProperties");
p.store(out, "---Thread Status----");
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run()
{
int i = 1;
String status = "1";
while("1".equals(status))
{
status = getStatus();
System.out.println("Loop " + i);
i++;
try { Thread.sleep(2000); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
public String getStatus() {
FileInputStream in;
Properties p = new Properties();
try {
in = new FileInputStream("appProperties");
p.load(in);
return p.getProperty("isRunning");
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//class StopThread
public class StopThread
{
public static void main(String[] args)
{
Properties p = new Properties();
p.setProperty("isRunning", "0");
FileOutputStream out;
try {
out = new FileOutputStream("appProperties");
p.store(out, "---Thread Status----");
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//class StopThread
public class StopThread
{
public static void main(String[] args)
{
Properties p = new Properties();
p.setProperty("isRunning", "0");
FileOutputStream out;
try {
out = new FileOutputStream("appProperties");
p.store(out, "---Thread Status----");
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Make thread t a public member of class MainThread, and then just call MainThread.t.interrupt() from StopThread
I am using an actionListener to trigger an sequence of events and ultimatley this code is called:
public class ScriptManager {
public static Class currentScript;
private Object ScriptInstance;
public int State = 0;
// 0 = Not Running
// 1 = Running
// 2 = Paused
private Thread thread = new Thread() {
public void run() {
try {
currentScript.getMethod("run").invoke(ScriptInstance);
} catch(Exception e) {
e.printStackTrace();
}
}
};
public void runScript() {
try {
ScriptInstance = currentScript.newInstance();
new Thread(thread).start();
State = 1;
MainFrame.onPause();
} catch (Exception e) {
e.printStackTrace();
}
}
public void pauseScript() {
try {
thread.wait();
System.out.println("paused");
State = 2;
MainFrame.onPause();
} catch (Exception e) {
e.printStackTrace();
}
}
public void resumeScript() {
try {
thread.notify();
System.out.println("resumed");
State = 1;
MainFrame.onResume();
} catch (Exception e) {
e.printStackTrace();
}
}
public void stopScript() {
try {
thread.interrupt();
thread.join();
System.out.println("stopped");
State = 0;
MainFrame.onStop();
} catch (Exception e) {
e.printStackTrace();
}
}
}
The runnable is created and ran, however, the problem occurs when I try to use the any of the other methods, they lock my UI. (I'm assuming this is because im running this on the EDT) Does anyone know how to fix this?
That's not how you use wait and notify. They need to be executed on the thread that you are trying to pause and resume. Which means you need to send a message to the other thread somehow. There are various ways to do this, but the other thread needs to be listening for this message, or at least check for it occassionally.