Break continuous loop with key - java

How do I break an infinity loop, like this one:
while(true){
if(???){
break;
}
}
Whitout interrupting it every time it loops and ask for input? The loop has to loop continuous until the user breaks it.
EDIT
I want to break it with a key input.

You could put the cycle in a separate thread.
import java.*;
import java.io.*;
class Main {
public static void main(String[] args) throws IOException {
Thread t = new Thread(new Runnable() {
public void run() {
int cnt = 0;
while (true) {
System.out.println(cnt);
++cnt;
}
}
});
t.start();
System.in.read();
t.stop();
}
}
Let's analyze it line by line; first the imports:
import java.*;
import java.io.*;
class Main {
Then we need to declare that main throws IOException, because we'll be dealing with IO calls; a better option is obviously to correctly handle exceptions, but this is just a simple test.
public static void main(String[] args) throws IOException {
Then we create a thread which executes an infinite cycle; we will not be doing IO calls from this thread. The thread is not started until we call Thread.start(), and will run until we call Thread.stop().
Thread t = new Thread(new Runnable() {
public void run() {
int cnt = 0;
while (true) {
System.out.println(cnt);
++cnt;
}
}
});
Now we start the thread; the lines after this call will keep executing concurrently with the thread, so we will be able to wait for user input and stop the thread.
t.start();
System.in.read();
t.stop();
}
}

I think your best option is to use a flag controlled by another thread. You could do something like this:
private volatile boolean keepRunning = true;
public synchronized void stopRunning() {
keepRunning = false;
}
public void someProcess() {
new Thread() {
public void run() {
try (Scanner scanner = new Scanner(System.in)) {
keepWaiting = true;
while(keepWaiting) {
String userInput = scanner.next();
if("s".equals(userInput)) {
stopRunning();
keepWaiting = false;
}
}
}
}
}.start();
while(keepRunning){
doWork();
}
}
The loop should keep running until the user enters "s". Of course it's a very basic implementation but you get the idea.
Also, you don't really need the "stopRunning()" method, the thread could access the flag directly, but you would need it if you wanted to run the thread from somewhere else.

It is better to use this.
boolean doLoop = true;
while(doLoop){
if(userTerminates()){ //user terminates it?
doLoop = false;
}
}
private boolean userTerminates(){
Scanner scanner = new Scanner(System.in);
//If you want that user terminates it with 'c' char
return scanner.nextLine().equals("c");
}

Related

Exercise on synchronization and threads

I'm doing a simple exercise to understand the concept of threads and synchronization. But I don't know whether the code is correct or not.
public class PopcornMachine {
// shared resource
private boolean isBinFull = false;
// producer method
public synchronized void placePopcorn () throws InterruptedException {
while (true) {
while (!isBinFull) wait ();
isBinFull = true;
System.out.println(isBinFull);
notify ();
Thread.sleep(1000);
}
}
// consumer code
public synchronized void takePopcorn () throws InterruptedException {
while (true) {
while (isBinFull) wait ();
isBinFull = false;
System.out.println(isBinFull);
notify ();
Thread.sleep(1000);
}
}
}
public class PopcornDemo {
public static void main (String[] args) throws InterruptedException{
final PopcornMachine machine = new PopcornMachine();
Thread produce = new Thread (new Runnable() {
public void run() {
try {
machine.placePopcorn ();
} catch(InterruptedException e) {}
}
});
Thread consume = new Thread (new Runnable() {
public void run() {
try {
machine.takePopcorn ();
} catch(InterruptedException e) {}
}
});
produce.start();
consume.start();
produce.join();
consume.join();
}
}
The answer I have is:
false
false
false
false
false
false
But it feels wrong. Isn't there a true value should come in the middle of the code?
Change the while condition like below and look at the comments . With your current code producer never executes.
Why? because isBinFull set to false initially and set to false in consumer too
and inside your producer code
while (!isBinFull) wait ();
will be never become false and keep waiting inside while loop.
Change the code like below
public synchronized void placePopcorn () throws InterruptedException {
while (true) {
while (isBinFull) wait(); //Look here, waiting since bin is full
isBinFull = true;
System.out.println(Thread.currentThread().getName() + ":"+isBinFull);
notifyAll ();
Thread.sleep(500);
}
}
// consumer code
public synchronized void takePopcorn () throws InterruptedException {
while (true) {
while (!isBinFull) wait(); ////Look here, waiting since bin is not full
isBinFull = false;
System.out.println(Thread.currentThread().getName() + ":"+isBinFull);
notifyAll ();
Thread.sleep(500);
}
}
using synchronised at method level itself makes sure only one thread executes at a time. synchronised keyword takes lock on the object it is being called i.e. machine in your case and hence the code is not a proper implementation of producer-consumer problem.

Two threads accessing same variable lock application

The following code was summed up the application, the application randomly was locked in
while (flag)
This code, running on my machine gets caught, in another machine he finished normally
The output generated here is:
INIT
END
before while
before flag
after flag
Code:
package threads;
public class Run implements Runnable {
private Thread thread;
private boolean flag = true;
public void init() {
thread = new Thread(this);
thread.setName("MyThread");
thread.start();
}
#Override
public void run() {
try {
int i = 0;
while (i < 1000) {
i++;
}
System.out.println("before flag");
flag = false;
System.out.println("after flag");
} catch (Exception e) {
e.printStackTrace();
} finally {
flag = false;
}
}
public void end() {
thread.interrupt();
thread = null;
System.out.println("before while");
while (flag) {
// try { Thread.sleep(100);} catch (InterruptedException e) {}
}
;
System.out.println("after while");
}
public static void main(String[] args) {
Run r = new Run();
System.out.println("INIT");
r.init();
System.out.println("END");
r.end();
}
}
Why when I change the value of flag the main thread does not pass through loop?
Change
private boolean flag = true;
to
private volatile boolean flag = true;
Without volatile, there is no guarantee the waiting thread needs to see the value get updated. HotSpot might even inline while(flag) to while(true) if the loop spins enough times.
See Memory Consistency Errors.
Also, what you're doing is called a spinlock. Normally you should use thread.join() instead. A spinlock is wasteful of resources because the waiting thread is actually working (checking a variable) the entire time it is supposed to be waiting.

Java thread lock when trying to lock/unlock with ReetrantLock(true)

I am having some trouble with a ReetrantLock(true) in an application that checks the difference between two images and shows similarity based on a percentage.
For some reason my input thread for reading in the minimum percent for being "similar" calls lock.lock() and that particular thread just deadlocks indefinitely but I can't seem to figure out why only that thread is deadlocking.
In the SSCCE below in the main method main(String[]) the inline Thread is used to get input from the console and if I type any number in it correctly stores it but as soon as it calls lock.lock() it deadlocks indefinitely and I am unsure why because the ReetrantLock has been told to be fair to caller threads and try to order them for when they called.
private static volatile boolean running = false;
public static void main(String[] args)
{
webcam2 webcam = new webcam2();
webcam.start();
(new Thread(new Runnable()
{
#Override
public void run()
{
Scanner scanner = new Scanner(System.in);
while (running)
{
System.out.print("Enter Double: ");
double val = scanner.nextDouble();
lock.lock(); // locks indefinatly here
if (val < 0.0D) reset = true;
dif = val;
System.out.println("Searching for value: " + dif);
lock.unlock();
}
scanner.close();
}
})).start();
}
private static double dif = 0.0D;
private static boolean reset = false;
private static ReentrantLock lock = new ReentrantLock(true);
#Override
public void run()
{
try
{
while (running)
{
// show image on window
lock.lock();
if (reset == true)
{
reset = false;
lock.unlock();
doComplexStuffToImage();
}
lock.lock();
doComplexStuffToImage();
lock.unlock();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static void doComplexStuffToImage()
{
try
{
Thread.sleep(1000);
}
catch(InterruptedException ie)
{
//swallow exception
}
}
public void start()
{
new Thread(this).start();
running = true;
}
public void stop()
{
running = false;
}
One thread is locking the ReentrantLock and not releasing it. What "reentrant" means is you can call lock many times, but you must call unlock() the same number of times. You lock twice, and unlock once so you are not actually unlocking the lock, thus no other process gets a chance.

Sleeping threads in JAVA

I am currently working on a project where I am to have essentially 10 threads that are "sleeping". At random one of these 10 threads is to "wake up" and start doing some work. I just want to see if I am headed in the right direction. So should I just create each instance of the thread for instance.
Thread thread0 = new Thread(new doWork());
...
Thread thread9 = new Thread(new doWork());
and just not start them and then when they are to "wake" just call the start() method on the particular thread..
or should I start each thread but have them wait() until I call the notify() method?
or should I start the thread and use sleep() and then call the interrupt() method?
Which approach seems to be better and why?
Any insight is greatly appreciated.
edit Will this be acceptable??
import java.util.Random;
public class Client {
private static Thread [] clients = new Thread[10];
public static void main(String[] args){
createClients();
randomWake();
}// end main()
static void createClients(){
Thread client0 = new Thread(new ClientThread(0));
clients[0] = client0;
Thread client1 = new Thread(new ClientThread(1));
clients[1] = client1;
Thread client2 = new Thread(new ClientThread(2));
clients[2] = client2;
Thread client3 = new Thread(new ClientThread(3));
clients[3] = client3;
Thread client4 = new Thread(new ClientThread(4));
clients[4] = client4;
Thread client5 = new Thread(new ClientThread(5));
clients[5] = client5;
Thread client6 = new Thread(new ClientThread(6));
clients[6] = client6;
Thread client7 = new Thread(new ClientThread(7));
clients[7] = client7;
Thread client8 = new Thread(new ClientThread(8));
clients[8] = client8;
Thread client9 = new Thread(new ClientThread(9));
clients[9] = client9;
for(int i = 0; i < clients.length; i++)
clients[i].start();
}// end createClients()
static void randomWake(){
Random rand = new Random();
int randomNumber = rand.nextInt(10);
clients[randomNumber].interrupt();
}// end randomWake()
static class ClientThread implements Runnable{
private int clientNumber;
public ClientThread(int clientNumber){
this.clientNumber = clientNumber;
}// end ClientThread(int clientNumber)
public void run(){
while(!Thread.interrupted()){}
System.out.println("Client " + clientNumber + " is awake!");
}// end run()
}// end class ClientThread
}// end class Client
In case there is a maximum amount of sleep time
You probably will need to implement the following Thread class:
public class DoWork extends Thread {
public void run () {
while(true) {
Thread.Sleep((int) Math.floor(Math.random()*10000));
//do some work
}
}
}
Where 10000 is the maximum time in milliseconds a thread should sleep.
In case there is no maximum amount of sleep time
You probably will need to implement the following Thread class:
public class DoWork extends Thread {
public void run () {
while(true) {
Thread.Sleep(1);
if(Math.random() < 0.005d) {
//do some work
}
}
}
}
where 0.005 is the probability of running the method a certain millisecond.
notify and wait are used to implement Semaphores: this are objects that prevent two threads to manipulate the same object at the same time (since some objects could end up in an illegal state).
How about using semaphores?
class DoWork extends Runnable {
private final Semaphore semaphore;
DoWork(Semaphore semaphore) {
this.semaphore = semaphore;
}
#Override
public void run() {
while (true) {
semaphore.acquire();
//do some work
}
}
}
The main program can create an array of Semaphores, and an equal number of Threads running DoWork instances, so that each DoWork instance has its own semaphore. Each time the main program calls sema[i].release(), The run() method of the corresponding DoWork instance will "do some work" and then go back to waiting.
It doesn't make much sense your answer, so not sure what you really want to achieve. But for what you describe you should put all threads waiting on the same lock and just notify the lock (it will awake only one randomly)
But as that doesn't make much sense, I guess you want to achieve something different.
Check this question regarding sleep vs wait: Difference between wait() and sleep()
Check this one. This is how I would solve it if I were not to use ThreadPooling (which is very correct as the others have said) and so that I can see how wait(),notify() and Thread.sleep() work. Checking google you will see (e.g. Thread.sleep and object.wait) that the mainly wait() and notify() are used for communication between threads and Thread.sleep is used so that you can pause your program.
-Part of this answer is based on this: http://tutorials.jenkov.com/java-concurrency/thread-signaling.html#missedsignals. You can check in the code to see the steps that you need to take (comment out some parts of the code) in order to make your program hang, so that you realize how to work with missed signals. The iterations needed for your program to hang are not fixed.
-The programm will run forever. You will need to work on it a bit in order to fix that.
Main
public class Main
{
public static void main(String[] args)
{
Manager mgr = new Manager("manager");
mgr.start();
}
}
Manager
public class Manager extends Thread
{
private final Object lock = new Object();
private boolean wasSignalled = false;
private DoWork[] workThreads = new DoWork[5];
public Manager(String name){
super(name);
workThreads[0] = new DoWork(this,"work 0");
workThreads[1] = new DoWork(this,"work 1");
workThreads[2] = new DoWork(this,"work 2");
workThreads[3] = new DoWork(this,"work 3");
workThreads[4] = new DoWork(this,"work 4");
}
public void wakeUP()
{
synchronized (this.lock) {
wasSignalled = true;
this.lock.notify();
}
}
public void pauseAndWait()
{
synchronized (this.lock) {
if(!wasSignalled)
{
try {
this.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//clear signal and continue running.
wasSignalled = false;
}
}
public void run ()
{
int i=0;
while(true)
{
i++;
System.out.println(" manager ...: "+i+" ");
int choose = 0 + (int)(Math.random() * ((4 - 0) + 1));
//choose=0; for debugginng
if(!workThreads[choose].isAlive()){
workThreads[choose].start();
}
else{
workThreads[choose].wakeUP();
}
//wait to be notified by DoWork thread when its job
//is done
pauseAndWait();
}
}
}
DoWork
public class DoWork extends Thread
{
private final Object lock = new Object();
private boolean wasSignalled = false;
private Manager managerThread;
public DoWork(Manager managerThread,String name){
super(name);
this.managerThread=managerThread;
}
public void wakeUP()
{
synchronized (this.lock) {
//check what happens without wasSignalled flag
//step #1: comment out wasSignalled = true;
wasSignalled = true;
this.lock.notify();
}
}
public void pauseAndWait()
{
synchronized (this.lock) {
//check what happens without wasSignalled flag
//step #2: comment out the if block
if(!wasSignalled)
{
try {
this.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//check what happens without wasSignalled flag
//step #3: comment out wasSignalled = false;
//clear signal and continue running.
wasSignalled = false;
}
}
public void run ()
{
int i=0;
while(true)
{
i++;
try {
System.out.print(this.getName()+" going to sleep ...: "+i+" ");
//check what happens without wasSignalled flag
//step #4: put sleep time to Thread.sleep(0);
//simulate worker thread job
Thread.sleep(1000);
System.out.println(" woke up ... ");
} catch (InterruptedException e) {
System.out.println(" worker thread: job simulation error:"+e);
}
//if worker thread job simulation is done (sleep for 4 times)
//then suspend thread and wait to be awaken again
if(i>4)
{
System.out.println(this.getName()+" notifying main ...: "+i+" \n");
i=0;
managerThread.wakeUP();
// thread does not get destroyed, it stays in memory and when the manager
// thread calls it again it will wake up do its job again
pauseAndWait();
}
}
}
}

How to make a while to run until scanner get input?

I'm trying to write a loop which runs until I type a specific text in console where the application is running. Something like:
while (true) {
try {
System.out.println("Waiting for input...");
Thread.currentThread();
Thread.sleep(2000);
if (input_is_equal_to_STOP){ // if user type STOP in terminal
break;
}
} catch (InterruptedException ie) {
// If this thread was intrrupted by nother thread
}}
And I want it to write a line each time it pass through so I do not want it to stop within the while and wait for next input. Do I need to use multiple threads for this?
Do I need to use multiple threads for this?
Yes.
Since using a Scanner on System.in implies that you're doing blocking IO, one thread will need to be dedicated for the task of reading user input.
Here's a basic example to get you started (I encourage you to look into the java.util.concurrent package for doing these type of things though.):
import java.util.Scanner;
class Test implements Runnable {
volatile boolean keepRunning = true;
public void run() {
System.out.println("Starting to loop.");
while (keepRunning) {
System.out.println("Running loop...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
System.out.println("Done looping.");
}
public static void main(String[] args) {
Test test = new Test();
Thread t = new Thread(test);
t.start();
Scanner s = new Scanner(System.in);
while (!s.next().equals("stop"));
test.keepRunning = false;
t.interrupt(); // cancel current sleep.
}
}
Yes, you would need two threads for this. The first could do something like this:
//accessible from both threads
CountDownLatch latch = new CountDownLatch(1);
//...
while ( true ) {
System.out.println("Waiting for input...");
if ( latch.await(2, TimeUnit.SECONDS) ) {
break;
}
}
And the other:
Scanner scanner = new Scanner(System.in);
while ( !"STOP".equalsIgnoreCase(scanner.nextLine()) ) {
}
scanner.close();
latch.countDown();

Categories

Resources