I'm writing a program that is meant to run through loops uninterrupted, with a user option to pause at any time. I want to use Scanner as a means for the user to input what they want to do to pause the program, but instead the program pauses every time it loops through, and the user is forced to input something before the code continues. My code looks like this:
for (int i = 0; i < 10; i++)
{
String pause = scan.next()
{
if (pause.equals("pause")
{
//break mechanism
}
}
}
Any ideas for how I could use this with a temporary pause? I was thinking maybe it could be something like "if 3 seconds pass, continue" but I'm not sure that would work, or how to code it. Thanks for any help.
Maybe like this:
while(scan.hasNext()) {
String pause = scan.next();
if (pause.equals("pause"))
{
//stop
}
}
As far as i understood it, your program stops, when the for-loop is done. Now the while-loop will be done when there is no more input.
maybe I think that it helps you with your idea
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.generic;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Scanner;
/**
*
* #author wilso
*/
public class prueba {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while (true) {
String pause = scan.next();
if (pause.toLowerCase().equals("pause")) {
System.out.println("Esperando quitar el modo pause");
pause = scan.next();
}
}
}
}
what I understood is this:
import java.util.Scanner;
public class Main
{
public static void main(String[] args) {
WorkerThread workerThread = new WorkerThread();
PausingThread pausingThread = new PausingThread(workerThread);
workerThread.start();
pausingThread.start();
}
}
class WorkerThread extends Thread{
#Override
public void run() {
while (true)
{
//Your work is being done
}
}
}
class PausingThread extends Thread{
WorkerThread workerThread;
PausingThread(WorkerThread thread){
this.workerThread = thread;
}
#Override
public void run() {
Scanner scan = new Scanner(System.in);
while (scan.next().equals("pause")){
try {
System.out.println("workerThread sleeping");
workerThread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
this will work...
Related
I'm creating a game and I'm stuck in this problem:
I have the class Game and inside the Game, I have the Kitchen.
When the player type for example: /new egg I do: game.kitchen.newEgg()
I would like to know what is the best way, and how I can notify the game that the Egg is finished.
I tried putting the class Game as static, but is doesn't seem correct.
I also tried every 1 second the game call kitchen.isReady() (neither this looks like correct)
and my last try was create a Consumer like this:
public class Kitchen {
public void newEgg(String name, Consumer<String> function){
System.out.println("egg is in progress");
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
function.accept(name);
}
}
and in the game:
public void createEgg(String eggName){
System.out.println("Creating an Egg");
Kitchen egg = new Kitchen();
Gamex x = new Gamex();
Runnable task2 = () -> { egg.newEgg(eggName, x::eggCreated); };
new Thread(task2).start();
System.out.println("game continue...");
}
public void eggCreated(String eggName) {
System.out.println("Egg: " + eggName + " finished.");
}
All the tree methods worked, but Is this the proper way to do?
How I should do it?
What is the best solution for a game?
Being notified that an asynchronous job is done would be a job for a CompletableFuture<V> (Java 8).
It is quite like a Future<V>, only you can attach to it additional callbacks that get triggered immediately when the job completes.
Here is a minimal working example that you could adapt to your game engine :
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Example {
public static void main(String[] args) {
Example example = new Example();
// Start generating a String
ExecutorService pool = Executors.newFixedThreadPool(4); // We need some pool to run things async
CompletableFuture.supplyAsync(example::createString, pool) // run the creation job in another thread
.thenAccept(example::callback); // run this callback when the job is done
pool.shutdown();
// Doing something else in the meantime...
System.out.println("Meandering...");
}
private String createString() {
artificialDelay();
return "Hello World";
}
private void callback(String input) {
System.out.println("Received this : " + input);
}
private void artificialDelay() {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
i've been making a countdown program, and i came up with this.
package main;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class Gatoo extends JFrame implements ActionListener {
private int sec, min, secTot, since = 999;
private long lastTime;
private JTextField mm = new JTextField(2), ss = new JTextField(2);
private JLabel minLab = new JLabel("Minutes:"), secLab = new JLabel(
"Seconds:");
private JButton start = new JButton("Start");
private Clip done;
private boolean started = false;
private static final long serialVersionUID = 4277921337939922028L;
public static void main(String[] args) {
Gatoo cake = new Gatoo("Title");
cake.pack();
cake.setSize(800, 600);
cake.setLocationRelativeTo(null);
cake.setDefaultCloseOperation(3);
cake.setVisible(true);
cake.run();
}
public Gatoo(String s) {
super(s);
setLayout(new FlowLayout());
start.addActionListener(this);
add(minLab);
add(mm);
add(secLab);
add(ss);
add(start);
}
#Override
public void actionPerformed(ActionEvent e) {
started = true;
}
public void play(File file) throws MalformedURLException,
UnsupportedAudioFileException, IOException,
LineUnavailableException {
AudioInputStream ais = AudioSystem.getAudioInputStream(new File(
"lib/done.wav"));
DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
done = (Clip) AudioSystem.getLine(info);
done.open(ais);
done.start();
}
public void run() {
while (true) {
System.out.print("");// needed?
if (started) {
try {
min = Integer.parseInt(mm.getText());
sec = Integer.parseInt(ss.getText());
secTot = (min * 60) + sec;
lastTime = System.currentTimeMillis();
while (secTot > 0) {
since = (int) (System.currentTimeMillis() - lastTime);
if (since > 998) {
lastTime = System.currentTimeMillis();
secTot--;
}
}
play(new File("done.wav"));
} catch (NumberFormatException exception) {
System.out.println("Minutes and seconds must be numbers.");
return;
} catch (Exception exception) {
exception.printStackTrace();
}
started = false;
}
}
}
}
In the while loop at the end the countdown code doesn't execute without a print / println statement inside. How come? The program works perfectly fine with the print statement though.
First and foremost, your program is thread-unsafe because boolean started is a shared variable, but it is neither volatile nor accessed within synchronized blocks.
Now, accidentally, PrintStream#print is a synchronized method and, on any actual architecture, entering and exiting a synchronized block is implemented using memory barrier CPU instructions, which cause a complete synchronization between the thread-local state and main memory.
Therefore, by pure accident, adding the print call allows the setting of started flag by one thread (the EDT) to be visible by another (the main thread).
You have poor design for Swing application.
Don't use while(true) loop in your run() method. Read more about Concurency in Swing.
Call events with help of Listeners(ActionListener e.g.) instead of flags(started here).
Instead of counting time use Swing Timer.
Change your run() method like next:
public void run() {
min = Integer.parseInt(mm.getText());
sec = Integer.parseInt(ss.getText());
secTot = (min * 60) + sec;
Timer timer = new Timer(1000*secTot, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
play(new File("done.wav"));
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
timer.start();
}
actionPerformed() method :
#Override
public void actionPerformed(ActionEvent e) {
run();
}
and remove cake.run() in main method.
Look, I made a SSCCE reproducing this behavior. It is a really good question.
public class ThreadRacing implements Runnable
{
public boolean started = false;
public static void main(String[] args)
{
new ThreadRacing().test();
}
public void test()
{
new Thread(this).start();
try
{
Thread.sleep(1000);
} catch (Exception e)
{
}
started = true;
System.out.println("I did my job");
}
#Override
public void run()
{
while (true)
{
//System.out.print("");
if (started)
{
System.out.println("I started!!");
}
}
}
}
This prints: "I did my job". Nothing more. Adding a volatile keyword actually fixes the problem.
To me, it looks like the second Thread gets not notified about the update to started because he is too bussy.
I would surmise that your busy-wait loop is hogging the CPU so severely it is unable to do anything. The print statement is causing just enough of a thread context switch that it is able to get other work done.
Edit: Okay, I did a little testing. I was able to reproduce OP's problem on the HotSpot Server VM. Using Thread.currentThread().setPriority(Thread.MIN_PRIORITY); did not fix it, so it is not a starvation issue. Setting the variable to volatile as #MartinCourteau, #MarkoTopolnik suggested, did fix it. That makes sense. I couldn't originally reproduce the problem on the HotSpot Client VM; apparently its optimizations are too weak for it to cache the started variable.
(Still, if the Java audio thread had a lower than normal thread priority and it were a single-CPU system, starvation was a plausible hypothesis.)
I am a beginner and I have to write a code for particular prob stmt. I wanna use locks to implement it. Beforehand, I gotto know the working of locks and its methods.
In my below code, I need the first thread to await and second thread to signal the first thread and wake up. But the signal is not waking up my waiting thread. Could anyone pls help.
package com.java.ThreadDemo;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadEx {
public static void main (String args[]) throws InterruptedException
{
ThreadMy mt[]=new ThreadMy[6];
int a=1, b=2;
mt[1] = new ThreadMy(a);
mt[2] = new ThreadMy(b);
mt[1].start ();
Thread.sleep(100);
mt[2].start ();
}
}
class ThreadMy extends Thread
{
final ReentrantLock rl = new ReentrantLock() ;
Condition rCond = rl.newCondition();
//private final Condition wCond = rl.newCondition();
int i;
int c;
public ThreadMy(int a)
{
c=a;
}
public void run()
{
System.out.print("\nThread "+c+" "+rl.isHeldByCurrentThread()+" "+rl.isLocked() );
rl.lock();
try
{
//for (i=0;i<2;i++)
System.out.print("\nThread "+c+" "+rl.isHeldByCurrentThread()+" "+rl.getHoldCount() );
try
{
if (c==1)
{
System.out.print("await\n");
rCond.await();
//rCond.await(200, TimeUnit.MILLISECONDS);
System.out.print("signal\n");
}
else
{
System.out.print("P");
rCond.signal();
Thread.sleep(2000);
System.out.print("P1");
}
//rCond.signal();
}
catch ( InterruptedException e)
{
//System.out.print("Exception ");
}
}
finally
{
rl.unlock();
}
System.out.print("\n run " + c);
}
}
You are not sharing lock and condition between threads. Each instance of ThreadMy is running with its own lock and condition object.
I am sorry that this is too long, and it may seem as too much asking, but If you can figure out what is wrong at a glance, please let me know.
In this program I try to input some words (phrase) from the keyboard every time taking one token and assign it to an object sharedStorer (then print the assigned value to keep track of what is input as I have a chain of words to input separately). This is done by one thread (Thread of class Retriever which implements Runnable)
There is another thread of class TokenReader that reads the value of sharedStorer and print it out. TokenReader waits for Retriever for input and when Retriever tries to input while TokenReader has not yet read the previous token Retriever waits.
The question I have is that at the end TokenReader waits forever for Retriever which has completed its task, and so the program never terminates.
Here is all 4 classes (and 1 Interface) I am using to perform the desired task.
package Multithreads;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExerciseTest {
public static void main(String[] args) {
ExecutorService app=Executors.newFixedThreadPool(2);
Storer st=new SyncStorer();
System.out.println("Operation performed\t\t Value");
try{
app.execute(new Retriever(st));
app.execute(new TokenReader(st));
}catch(Exception e){
e.printStackTrace();
}
app.shutdown();
}
}
package Multithreads;
public interface Storer {
public void set(String token);
public String get();
}
package Multithreads;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Scanner;
import java.util.StringTokenizer;
public class Retriever implements Runnable {
private Scanner scanner;
private String token;
private String currentToken;
private Storer sharedStorer;
private Random rd=new Random();
public int tokenLength=0;
public Retriever(Storer st) {
sharedStorer=st;
}
public Retriever() {
}
#Override
public void run() {
System.out.println("Enter a phrase");
scanner = new Scanner(System.in);
token=scanner.nextLine();
StringTokenizer tokenizer=new StringTokenizer(token);
while(tokenizer.hasMoreTokens())
{
tokenLength++;
currentToken=tokenizer.nextToken();
try{
Thread.sleep(10*rd.nextInt(2000));
sharedStorer.set(currentToken);
}catch(NoSuchElementException e){
e.printStackTrace();
}catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println("Done Inputting The phrase");
}
}
package Multithreads;
import java.util.Random;
public class TokenReader implements Runnable {
private Random rd=new Random();
private Storer sharedStorer;
Retriever rtr=new Retriever();
private int count=rtr.tokenLength;
public TokenReader(Storer st) {
sharedStorer=st;
}
#Override
public void run() {
String str="null";
int i=0;
try {
while(i <= count){
Thread.sleep(15*rd.nextInt(2000));
str=sharedStorer.get();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consumer done reading");
}
}
package Multithreads;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SyncStorer implements Storer {
private Lock accessLock=new ReentrantLock();
private Condition canInput = accessLock.newCondition();
private Condition canRead = accessLock.newCondition();
private String string="null";
private boolean isEmpty=false;
#Override
public void set(String token) {
accessLock.lock();
try
{
while(isEmpty){
System.out.println("Retriever waiting");
canInput.await();
}
string=token;
isEmpty=true;
System.out.println("Retriever inputs\t\t "+string);
canRead.signal();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
accessLock.unlock();
}
}
#Override
public String get() {
accessLock.lock();
try{
while(!isEmpty)
{
System.out.println("No token to read");
canRead.await();
}
isEmpty=false;
System.out.println("TokenReader reads\t\t "+string);
canInput.signal();
}catch(InterruptedException e)
{
e.printStackTrace();
}finally{
accessLock.unlock();
}
return string;
}
}
The problem that is causing the app to run forever is that this is an infinite loop:
while(i <= count){
Thread.sleep(15*rd.nextInt(2000));
str=sharedStorer.get();
}
because you are not decrementing i. And the interrupt-based mechanism you are trying to use to break out of the loop (via an exception!) is broken too.
The Thread.sleep(15*rd.nextInt(2000)) line looks like a hack so that you can get an InterruptedException when the task is interrupted, but:
the point of sleeping for a random number of milliseconds escapes me, and
it would be simpler to just call Thread.interrupted().
Besides, the approach isn't reliable anyway because there is a chance that the interrupt will happen after the point at which you are waiting / testing for it; i.e. in the get() call. And if that get() call is never going to return because the store is empty and the retriever has ended ... then you will wait "for ever".
There is one final problem. You need to call app.shutdownNow() if you want the executor service to interrupt the worker threads ...
If I was trying to implement this (using interrupts), I'd change it so that get and set didn't "gobble up" the interrupt. If they see the interrupt, they should either:
allow the InterruptedException to propagate (after relevant cleanup), or
set the thread's interrupted flag again in the exception handler.
I have a thread, that processes incomming messages (endless loop). For this, I use a BlockingQueue (Java), which works as quite nice. Now, I want to add a second processor in the same Class oder method. The problem now is, that in the endless loop i have this part
newIncomming = this.incommingProcessing.take();
This part blocks if the Queue is empty. I'm looking for a solution to process to queues in the same class. The second queue can only processed, it some data is coming in for the first Queue.
Is there a way to handle tow blocking queues in the same endless loop?
Either you need two threads or you need them to share the same blocking queue. (Or you need to use a different structure than blocking queue)
BlockingQueue is meant for multiple thread implementations. Instead, use a simple Queue. See this.
I am not sure what you are trying to do, but if you do not want the thread to block on the queue if it is empty, you can use BlockingQueue.peek() to first check if the queue is empty or not.
What I understand from your question I came up with the following
Code snippet
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package blockingqueues;
import java.io.BufferedReader;
import java.io.Console;
import java.io.InputStreamReader;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
*
* #author alfred
*/
public class BlockingQueues {
private static String take(BlockingQueue<String> bq) {
try {
return bq.take();
} catch(InterruptedException ie) {
return null;
}
}
public static void main(String args[]) throws Exception {
final BlockingQueue<String> b1 = new LinkedBlockingQueue<String>();
final BlockingQueue<String> b2 = new LinkedBlockingQueue<String>();
ExecutorService es = Executors.newCachedThreadPool();
es.execute(new Runnable() {
public void run() {
while (true) {
String results = take(b1);
if (results == null) {
break;
}
System.out.println("first: " + results);
}
}
});
es.execute(new Runnable() {
public void run() {
while (true) {
String results = take(b2);
if (results == null) {
break;
}
System.out.println("second: " + results);
}
}
});
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
String input = null;
System.out.println("type x to quit.");
while (!"x".equals(input)) {
input = br.readLine();
if (input.startsWith("1 ")) {
// Add something to first blocking queue.
b1.add(input.substring(2));
} else if (input.startsWith("2 ")) {
// Add something to second blocking queue.
b2.add(input.substring(2));
}
}
es.shutdownNow();
es.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("bye!");
br.close();
}
}
Executing program:
You can enter text from console to add task to blockingqueue b1 or b2. If your console input starts with a 1 like for example input = "1 hello" then the b1 will process task(print first: hello) else if input starts with a 2 like for example input = "world" then b2 will print second: world.