I'm currently writing a simple java app. I have a menu where I can perform different functions. What I'm wanting to do is execute a process, and while that process is running, still be able to navigate around the app, choosing different options from the menu. I also want to be able to stop the process from the menu.
So suppose I had this:
public class UserInterface {
Console c = System.console();
boolean quitFlag = false;
public void userInput()
{
String choice = c.readline("> ");
while(choice != "exit")
{
switch(choice){
case "1":
startProcess();
break;
case "2":
endProcess();
break;
}
}
public void startProcess()
{
int i = 0;
while(!quitFlag)
i = i + 1;
}
public void endProcess()
{
quitFlag = true;
}
}
How would I go about letting startProcess() continue while executing userInput()? Is there a general principle for this? How would I do it if startProcess() and endProcess() were in different classes?
There are several ways to do this but the simplest is via the Thread class. The Java docs for java.lang.Thread show examples, but the principle is that you place your separate process code inside a Thread subclass or in the run() method of a Runnable interface implementation which is passed to the Thread.
Call start() or run() on the thread to start processing. The UI thread continues independently.
Although Thread includes a stop() method, it is deprecated and the Java docs explain why. Best practice is to create your own method that sets a flag indicating that the process should end early, and then check this flag at frequent intervals.
Something like:
public class UserInterface {
MyProcessor processor = null;
...
public void startProcess() {
processor = new MyProcessor();
new Thread(processor).start();
}
public void endProcess() {
if (processor != null) {
processor.endProcess();
}
}
private class MyProcessor implements Runnable {
private boolean quitFlag = false;
#Override
public void run() {
int i = 0;
while (!quitFlag) {
i = i + 1;
}
}
public void endProcess() {
quitFlag = true;
}
}
}
Related
I have the next sample I am trying to run, but sometimes it runs fine, another it is not exiting the loop. I can imagine only that for some reason values are skipping.
By skipping the values I mean the flags meant to notify the loop in the class Flasher to exit, which are brought from class engine, ass well the flags meant to notify the loop in class Engine from class Flasher.
This is how I understood it could run the best possible and simplest way, but what is going on?
Can you please help?
//Main class:
public class Flasher {
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
engine en1 = new engine("ZaikoBaiko");
engine en2 = new engine("MiliVaninili");
en1.start();
en2.start();
int Terminator2 = 0;
while(!en1.Terminator||!en2.Terminator)
{
}
System.out.println(" owns the last word");
en1.roboCop = true;
en2.roboCop = true;
}
}
//Thread Class:
public class engine extends Thread
{
public String OB;
public boolean Terminator = true;
public boolean roboCop = false;
private Thread t;
engine(String name)
{
OB = name;
Terminator = false;
}
#Override
public void run()
{
int x = 0;
while(x<100)
{
System.out.println(x+":"+OB);
x++;
}
Terminator = true;
while(!roboCop){}
}
#Override
public void start()
{
if(t==null)
{
t = new Thread(this,OB);
t.start();
}
}
}
The JVM is caching your variables. You need to add volatile to your check variables (Terminator, roboCop). This will ensure that all threads write/read the newest value to/from main memory.
For a detailed explanation here is a similar question!
I tried using a volatile boolean to act as a flag to stop/start/restart the action in the thread, however it does not work. It just keeps on going forever and never terminates. Any help on how to properly do this or why my code does not work will be greatly appreciated. Thanks in advance.
public class thread {
public static int i = 0;
private static Thread print = null;
private static printThread runnable = null;
public static void main(String[] args) {
runnable = new printThread();
print = new Thread (runnable);
print.start();
System.out.println("Starting");
runnable.begin();
if(i > 5)
{
runnable.terminate();
}
i = 10;
runnable.begin();
if(i > 15)
{
runnable.terminate();
}
}
public static final void print()
{
System.out.println(i);
i++;
}
public static final class printThread implements Runnable {
private volatile boolean running = false;
public void terminate() {
running = false;
}
public void begin() {
running = true;
}
public boolean isRunning() {
return running;
}
public void run() {
while(true)
{
if(running)
{
print();
}
else
{
}
}
}
}
}
In your code while loop execution never ends. You could introduce 2 states: terminated and waiting to simulate threads start/pause/restart/stop. However, even if you pause the Thread it will be running, just different branch of code will be executed inside while loop.
Please, see the code snippet below
public static final class printThread implements Runnable {
private volatile boolean waiting = false;
private volatile boolean terminated = false;
public void terminate() {
terminated = true;
}
public void pause() {
waiting = true;
}
public void restart() {
waiting = false;
}
public void run() {
while(!terminated) {
if(waiting) {
//the thread is paused
} else {
//the thread is running
}
}
}
}
however it does not work. It just keeps on going forever and never terminates.
In your run() method of your thread, you aren't watching for the value of your volatile boolean running field. It probably should be something like:
public void run() {
while(!running) {
print();
// you might want a short Thread.sleep(10); here to stop the spinning
}
}
However, as #Anton points out, once your thread terminates, it can't be restarted without some other flag. See his answer.
Also, you are sharing i between the main thread and the your printing thread. That also needs to be volatile so it can be properly shared. Since you are incrementing it in multiple threads, you should use an AtomicInteger for that.
public static AtomicInteger i = new AtomicInteger();
...
if (i.get() > 5) ...
...
i.set(10);
...
i.incrementAndGet();
Couple of other comments:
Be careful of static fields. print and runnable should be defined only inside of the main(...) method to restrict access.
Classes should begin with an uppercase letter so it should be PrintThread.
Actually, because PrintThread isn't a thread, it should be PrintRunnable or maybe even better, Printer.
Let's say that I have an algorithm that does something for a given parameter. If the algorithm runs longer than 100 miliseconds then I want to stop it and try again for a different parameter.
I posted below the code that would test the algorithm for a random parameter... and how I think the code might look like:
public class StopThread {
private Lock lock = new ReentrantLock();
public static void main(String... args) {
System.out.println("Starting threads...");
(new StopThread()).startThreads(100);
}
private void startThreads(int nrOfThreads) {
for (int i = 0; i < nrOfThreads; i++) {
startThread(i, (long) (Math.random() * 10000000000l));
System.out.println("Started thread number " + (i + 1));
}
}
private void startThread(final int number, final long load) {
Thread workerThread = new Thread() {
#Override
public void run() {
try {
lock.lock();
doAlgorithmWork(load);
} finally {
System.out.println("Thread " + (number + 1) + " finished...");
lock.unlock();
}
}
};
Thread timerThread = new Thread() {
#Override
public void run() {
try {
sleep(100);
} catch (InterruptedException e) {
}
}
};
workerThread.start();
timerThread.start();
do {
if (!workerThread.isAlive() || !timerThread.isAlive()) {
workerThread.stop();
timerThread.stop();
}
} while (!workerThread.isAlive() && !timerThread.isAlive());
}
protected void doAlgorithmWork(long load) {
while (load-- > 0) {
}
}
}
I feel like this question should already have an answer, but what I found until now seemed complicated and I didn't know how to use it. I'm not that knowledgeable with threads and I would appreciate if you could post some code.
A very simple solution would look like this:
private void startThreads(int nrOfThreads) {
for (int i = 0; i < nrOfThreads; i++) {
Thread worker = new Thread() {
#Override
public void run() {
doAlgorithmWork((long) (Math.random() * 10000000000l));
}
}
worker.start();
worker.join(100); //block until either the thread is done, or 100ms passed
if (worker.isAlive()) worker.stop(); //if thread is still alive, stop it
}
}
This will achieve your goal, but suffers from a number of "drawbacks"
It is single threaded (that is, all calls to doAlgorithm execute one after another, instead of in parallel, so you are only using a single core of your machine);
It uses the discouraged Thread.stop() method. A preferred approach is to instead have a "stop" flag which is set to true (in place of the stop() call), and which is also constantly checked for in doAlgorith;
It creates a new thread for each doAlgorithm call (instead of reusing a single thread), which is "wasteful", but for your case probably has little practical implications
UPDATE:
In order to avoid the deprecated stop() call, you will need to add a flag to your worker thread, creating a separate class like this:
public class Worker implements Runnable {
private volatile boolean stopped = false;
public void stop() {
stopped = true;
}
#Override
public void run() {
doAlgorithmWork((long) (Math.random() * 10000000000l));
}
private void doAlgorithmWork(long load) {
while (!stopped && load-- > 0) {
//calculation
}
}
}
Then your runner looks like this:
private void startThreads(int nrOfThreads) {
for (int i = 0; i < nrOfThreads; i++) {
Thread worker = new Thread(new Worker());
worker.start();
worker.join(100); //block until either the thread is done, or 100ms passed
if (worker.isAlive()) worker.stop(); //if thread is still alive, stop it
}
}
You could also create a constructor for Worker which accepts the load value (instead of having it generated inside the Worker itself).
Note that if the calculation inside doAlgorithm() is too time-consuming, the thread may run for more than 100ms (since it always completes each calculation within the loop). If this is an issue, then your alternative is to interrupt the thread instead (calling worker.interrupt() will cause an InterruptedException to be thrown within the run() method).
I'm working on making an interface for a robot. My Robot class has methods that include movement, stopping movement and reading sensor data. If at all possible, I'd like to have certain methods run under a given thread and certain other methods run under another. I'd like to be able to send the command to move to the robot object, have the thread executing it sleep duration milliseconds and then stop movement, but I'd like the stop() method able to be called and interrupt the thread executing the movement. Any help is greatly appreciated.
public class robotTest
{
public static void main(String[] args) throws InterruptedException
{
Robot robot = new Robot(); //Instantiate new Robot object
robot.forward(255, 100, Robot.DIRECTION_RIGHT, 10); //Last argument representing duration
Thread.sleep(5000); //Wait 5 seconds
robot.stop(); //Stop movement prematurely
}
}
I would suggest instantiating your Robot class with an ExecutorService that you can use for moving asynchronusly. Submit the movement request to your service and use the Future returned to 'stop' the move request.
class Robot{
final ExecutorService movingService = Executors.newSingleThreadExecutor();
private volatile Future<?> request; //you can use a Deque or a List for multiple requests
public void forward(int... args){
request = movingService.submit(new Runnable(){
public void run(){
Robot.this.move(args);
}
});
}
public void stop(){
request.cancel(true);
}
}
If I'm understanding you correctly then yes, you can call methods on an object from any given thread. However, for this to work in a bug free fashion the robot class needs to be thread safe.
Make sure all your calls to Robot come from a thread (a class extending Thread that you create) with permissions to make the calls. Add this method to your call.
Note: this code is far from perfect. But it may give you some ideas you can use in your application.
public void stop() throws NoPermissionException {
checkStopPermission(); // throws NoPermissionException
// rest of stop here as normal
}
/**
* Alternatively you could return a boolean for has permission and then throw the NoPermissionException up there.
*/
private void checkStopPermission() throws NoPermissionException() {
try {
Thread t = Thread.currentThread();
RobotRunnableThread rrt = (RobotRunnableThread)t; // may throw cast exception
if(!rrt.hasPermission(RobotRunnableThread.STOP_PERMISSION)) { // assume Permission enum in RobotRunnableThread
throw new NoPermissionExeception();
}
} catch(Exception e) { // perhaps catch the individual exception(s)?
throw new NoPermissionException();
}
}
You have to start a new background thread when you instantiate a Robot that would handle movement. The thread would sit there, waiting for a signal from forward or stop and do the appropriate thing.
You will have to synchronize the threads using either semaphores, wait handles, or other inter thread communication elements.
The least robust solution that wastes the most CPU (this is pseudo code since I have not used Java in a while, might be intermixed with .NET APIs):
public class Robot implements IRunnable {
public Robot() {
new Thread(this).Start();
}
private int direction = 0;
private int duration = 0;
private bool go = false;
public void Run() {
DateTime moveStartedAt;
bool moving = false;
while(true) {
if(go) {
if(moving) {
// we are already moving
if((DateTime.Now - moveStartedAt).Seconds >= duration) {
moving = false;
}
} else {
moveStartedAt = DateTime.Now;
moving = true;
}
} else {
moving = false;
}
}
}
public void forward(int direction, int duration) {
this.direction = direction;
this.duration = duration;
this.go = true;
}
public void stop() {
this.go = false;
}
}
(the above code should be modified to be Java for better answer)
What is wrong with this code:
The Run() method consumes one whole Core (it has no sleeps)
Calling stop() and then forward() right away can result in a race condition (the Run() has not seen the stop yet, but you already gave it another forward)
There is no way for Run() to exit
You can call forward() to redirect the move that is already in progress
Others?
I would like to determine the exit status of the process during the shutdown hook runtime.
I want to have a logic which is based on the status code (0 or nonzero)
(ex: if zero do nothing else nonzero send an alert email)
Do you know how I can get this information?
I tried to override the SecurityManager checkExit(int status) method - this works if System.exit(status) is called anywhere explicitly - however, it doesn't set the status when the application exits "normally" (no active threads), or an error kills the VM.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.Permission;
public class ExitChecker {
public ExitChecker() {
System.setSecurityManager(new ExitMonitorSecurityManager());
Runtime.getRuntime().addShutdownHook(new Thread(new MyShutdownHook()));
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String line = "";
while (!line.equalsIgnoreCase("Q")) {
try {
System.out.println("Press a number to exit with that status.");
System.out.println("Press 'R' to generate a RuntimeException.");
System.out.println("Press 'O' to generate an OutOfMemoryError.");
System.out.println("Press 'Q' to exit normally.");
line = input.readLine().trim();
processInput(line);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
}
private void processInput(String line) {
if (line.equalsIgnoreCase("Q")) {
// continue, will exit loop and exit normally
} else if (line.equalsIgnoreCase("R")) {
throwRuntimeException();
} else if (line.equals("O")) {
throwError();
} else {
// try to parse to number
try {
int status = Integer.parseInt(line);
callExit(status);
} catch(NumberFormatException x) {
// not a number.. repeat question...
System.out.println("\nUnrecognized input...\n\n");
}
}
}
public void callExit(int status) {
System.exit(status);
}
public void throwError() {
throw new OutOfMemoryError("OutOfMemoryError");
}
public void throwRuntimeException() {
throw new RuntimeException("Runtime Exception");
}
public static void main(String[] args) {
new ExitChecker();
}
private static class ExitMonitorSecurityManager extends SecurityManager {
#Override
public void checkPermission(Permission perm) {
//System.out.println(perm.getName());
//System.out.println(perm.getActions());
}
#Override
public void checkPermission(Permission perm, Object context) {
//System.out.println(perm.getName());
//System.out.println(perm.getActions());
}
#Override
public void checkExit(int status) {
System.out.println("Setting exit value via security manager...");
MyShutdownHook.EXIT_STATUS = status;
}
}
private static class MyShutdownHook implements Runnable {
public static Integer EXIT_STATUS;
public void run() {
System.out.println("In MyShutdownHook - exit status is " + EXIT_STATUS);
}
}
}
Here is some example code whereby a dedicated class is used to initiate a System.exit call via a call to doExit(int). The class also stores the exit status and subsequently acts as a shut-down hook.
public class ShutDownHook implements Runnable {
private volatile Integer exitStatus;
// Centralise all System.exit code under control of this class.
public void doExit(int exitStatus) {
this.exitStatus = exitStatus;
System.exit(exitStatus); // Will invoke run.
}
public void run() {
// Verify that an exit status has been supplied.
// (Application could have called System.exit(int) directly.)
if (this.exitStatus != null) {
switch(exitStatus) {
case 0: // Process based on exit status.
// Yada yada ...
}
}
}
}
Why do this in the application itsellf? If your application is not sending a e-mails as part of normal operations, incorporating this kind of functionality is not a good idea, IMHO.
I would just trust to setting an appropriate return value from the JVM process and let a shell script or whatever take care of the conditional creation of the e-mail.
Shutdownhooks are supposed to run for a short time only, sending an e-mail could consume quite some time.
You must save the exit status in main into a global (public static) variable.