multithreading in java - java

I want "runnable" to run at 5tps. This is not executing paralelly.
package tt;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
public class mySpawner {
public int tillDone = 0;
public int tillMax = 0;
public ArrayList arrayList;
private myWorker myworking;
private ScheduledExecutorService service = Executors.newScheduledThreadPool(50);
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
System.out.println(System.nanoTime());
Thread.sleep(7000);
} catch (InterruptedException ex) {
Logger.getLogger(mySpawner.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
public void activate() {
try {
service = Executors.newScheduledThreadPool(50);
service.scheduleAtFixedRate(runnable, 0, 200, TimeUnit.MILLISECONDS);
} catch (Exception e) {//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
public void deactivate() {
service.shutdown();
}
}

Consider this:
Your tasks are sleeping for 7 seconds during their execution
You are scheduling a new task every 200ms
You only have 50 threads in your executor
It should be clear, I hope, that you'll run out of pooled threads in just a few seconds, and you'll lose your parallelism. You need to balance this better, either by reducing the rate or reducing the sleep. Increasing the pool size won't help, you'll still run out of threads.

scheduleAtFixedRate does only spawn a single thread but executes the runnable provided with a fixed rate.
The action runs in less amount of time than the given period: in this case it is respawned with exactly the specified period.
The action runs longer (your case): the action is started again immediately.
If you want to have the desired behaviour you may use the following pattern: Just execute the runnable once:
service.schedule(runnable, 0, TimeUnit.MILLISECONDS);
but inside the runnable's run method add the next invokation by
service.schedule(runnable, 200, TimeUnit.MILLISECONDS);
Nevertheless consider the arithmetic as described in the answer by skaffman.

Update: Howard is right, my first example was wrong.
I verified this works if you change your active() method:
service = Executors.newScheduledThreadPool(50);
new Thread() {
public void run() {
long nextTime = System.currentTimeMillis();
while (true) {
service.submit(runnable);
long waitTime = nextTime - System.currentTimeMillis();
Thread.sleep(Math.max(0, waitTime));
nextTime += 200;
}
}
}.start();

Related

How do I wait for a command to finish executing before stopping the program?

Here is my code:
import java.io.File;
import jaco.mp3.player.MP3Player;
class SimpleAudioPlayer {
public static void main(String[] args) {
File audio_file = new File("Clarx - H.A.Y.mp3");
MP3Player music_player = new MP3Player();
music_player.addToPlayList(audio_file);
music_player.play();
// wait for music_player.play() to finish executing
}
}
I wanted to create an mp3-player and found this Project, what the code snippet does is creating a new MP3Player object, creating a new File, and adding it to the Playlist. After that, it just starts playing the song. But the problem is that it just plays about one or two seconds of the file before the program stops executing. How can I wait until the play() function has stopped executing?
Answer:
Thanks to giraycoskun for this!
import java.io.File;
import jaco.mp3.player.MP3Player;
import java.util.concurrent.*;
class SimpleAudioPlayer {
public static void main(String[] args) {
File audio_file = new File("Clarx - H.A.Y.mp3");
MP3Player music_player = new MP3Player();
music_player.addToPlayList(audio_file);
ExecutorService threadpool = Executors.newCachedThreadPool();
Future<Long> futureTask;
futureTask = (Future<Long>) threadpool.submit(music_player::play);
// Simple variable to check hpw often the folowing loop gets executed
int n = 0;
while (!futureTask.isDone()) {
System.out.println("Executing" + n);
n++;
}
}
}
I had to do some minor changes to the answer he submitted, but it works great, thank you very much!
I haven't tried the code on my computer however these can help:
https://docs.oracle.com/javase/8/docs/api/?java/util/concurrent/package-summary.html
https://www.baeldung.com/java-asynchronous-programming
import java.io.File;
import jaco.mp3.player.MP3Player;
import java.util.concurrent;
class SimpleAudioPlayer {
public static void main(String[] args) {
File audio_file = new File("Clarx - H.A.Y.mp3");
MP3Player music_player = new MP3Player();
music_player.addToPlayList(audio_file);
ExecutorService threadpool = Executors.newCachedThreadPool();
Future<Long> futureTask = threadpool.submit(() -> music_player.play());
while (!futureTask.isDone()) {
// wait for music_player.play() to finish executing
System.out.println("FutureTask is not finished yet...");
}
}
}

Java ScheduledExecutorService wait until a resource is available

I have a problem with my java application. On the startup of the application the application needs a connection to another application. My idea was to check on startup of my application to check every second if the other application is available (no condition like wait 5 Minutes, just wait infinitly until available).
I tryed this in the abstract example shown below. In the excample my application will get the other application after 3 trys ...
package main;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Main {
private static final Logger logger = LogManager.getLogger(Main.class);
public static void main(String[] args) {
final Callable<String> sleeper = new Callable<String>() {
// local timer for resource getter
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
ScheduledFuture<?> timer;
String returnValue;
#Override
public String call() throws Exception {
// start on first call
if (null == timer) {
logger.info("sleeper - starting getter ...");
timer = executor.scheduleAtFixedRate(new getter(3), 0, 1, TimeUnit.SECONDS);
}
// the right way - this seems to be ugly!
try {
timer.get();
} catch (CancellationException | ExecutionException | InterruptedException e) {
logger.error("sleeper - got an exception ... but nothing bad?!");
}
logger.info("sleeper - returning="+returnValue);
return returnValue;
}
class getter implements Runnable {
int _trys;
int _maxTrys;
String _res = null;
getter(int maxTrys) {
logger.info("getter - init, maxTrys=" + maxTrys);
_maxTrys=maxTrys;
}
#Override
public void run() {
if (null == _res) {
if (_trys<_maxTrys) {
++_trys;
logger.info("getter - sleeping trys="+_trys + "/" + _maxTrys);
} else {
_res = "*MIGHTY RESOURCE*";
logger.info("getter - found resource after "+_trys+" trys!");
}
} else {
logger.info("getter - returning resource to parent");
returnValue = _res; // hand over
this.notify(); // exit?
}
}
}
};
logger.info("Main - starting sleeper");
ScheduledExecutorService sleeperExecutor = Executors.newScheduledThreadPool(1);
Future<String> resource = sleeperExecutor.submit(sleeper);
try {
logger.info("Main - got="+resource.get());
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}
}
This seems to be a bad solution for me because I can only exit with an exception (see timer.get()). And it seems to be very mich code for such a simple problem.
I imagine something like this (pseudo code):
Application {
start() {
while (!otherAppl.isAvailable) {
// wait until other appl is available
}
// other application is available ... go on with startup
}
}
Regards
S.

Java SchedulerExecutor

Recently I wrote code that had to limit request throughput. I used ScheduleExecutorService.scheduleAtFixedRate and I believed that it should do the work (It did!) but I wrote some test to check time of scheduled task and i was amazed. First few tasks weren't scheduled as javadoc explain with n*period. Can anyone explain me what am I missing?
If it work that way then why it is not mentioned in javadoc? And then question is how exactly scheduler work?
I would like to avoid looking into sources:)
Example:
import java.time.Duration;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ExecutorTest {
Executor executor;
ScheduledExecutorService schedulingExecutor;
BlockingQueue<LocalTime> times;
public static void main(String[] args) throws InterruptedException {
new ExecutorTest().start();
}
public ExecutorTest() {
schedulingExecutor = Executors.newScheduledThreadPool(1);
executor = Executors.newCachedThreadPool();
times = new LinkedBlockingQueue<>();
}
public void start() throws InterruptedException {
schedulingExecutor.scheduleAtFixedRate(this::executeTask, 0, 50, TimeUnit.MILLISECONDS);
LocalTime nextEvaluatedTime = times.take();
LocalTime time = nextEvaluatedTime;
while (true) {
System.out.println(String.format(String.join(" ", "recorded time: %d", "calculated proper time: %d", "diff: %d"),
time.toNanoOfDay(),
nextEvaluatedTime.toNanoOfDay(),
Duration.between(nextEvaluatedTime, time).toNanos()));
nextEvaluatedTime = time.plus(50, ChronoUnit.MILLIS);
time = times.take();
}
}
private void executeTask() {
executor.execute(() -> {
times.add(LocalTime.now());
});
}
}
If you run this program you could see that few first time wasn't recorded as expected. Why?

Cannot change boolean value in method

I've got a little problem. I'm playing mp3 using Java sound sampled and I want to stop playing when I click the button. So I came up with something like this:
package sk.umb.osadnici.Client.Core.getterImages;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine.Info;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.FloatControl;
import javazoom.jl.player.advanced.AdvancedPlayer;
import static javax.sound.sampled.AudioSystem.getAudioInputStream;
import static javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED;
public class GetterForBGMusic {
private SourceDataLine line;
private URL url;
public URL bgUrl, bgUUUrl;
private boolean canPlay = true;
public void runMusic() {
final GetterForBGMusic player = new GetterForBGMusic();
player.play();
}
public void play() {
URL inTTT = getClass().getResource("../sounds/bgMusic.mp3");
try (AudioInputStream in = getAudioInputStream(inTTT)) {
AudioFormat outFormat = getOutFormat(in.getFormat());
Info info = new Info(SourceDataLine.class, outFormat);
try (SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info)) {
if (line != null) {
System.out.println(canPlay);
line.open(outFormat);
line.start();
stream(getAudioInputStream(outFormat, in), line);
line.drain();
line.stop();
}
}
} catch (UnsupportedAudioFileException
| LineUnavailableException
| IOException e) {
throw new IllegalStateException(e);
}
}
private AudioFormat getOutFormat(AudioFormat inFormat) {
final int ch = inFormat.getChannels();
final float rate = inFormat.getSampleRate();
return new AudioFormat(PCM_SIGNED, rate, 16, ch, ch * 2, rate, false);
}
private void stream(AudioInputStream in, SourceDataLine line)
throws IOException {
while (true) {
System.out.println(this.getCanPlay());
}
}
public void setCanPlay(boolean play) {
this.canPlay = play;
}
public boolean getCanPlay() {
return canPlay;
}
private void booleanValue() {
while (true)
System.out.println(canPlay);
}
}
Im using this code, if i call booleanValue method in constructor, everything is fine. but if call this method inside stream there is no change after value change.
Or can someone tell me how to stop this: http://odoepner.wordpress.com/2013/07/19/play-mp3-or-ogg-using-javax-sound-sampled-mp3spi-vorbisspi/
Your program is single-threaded, which means that it executes the sequence of "commands" you programmed from top to bottom.
For example, in this example
setCanPlay(true);
play(); //your for loop
setCanPlay(false);
the setCanPlay(false) instruction will only execute once the for loop has finished executing.
What you need is to have the for loop running in the background, and to be able to modify canPlay while the for loop is running. That's called multi-threading and you should lookup the classes Runnable, Task and Service in the java api doc to learn how to implement it.
You would end up with something like this:
setCanPlay(true);
play(); //your for loop, launched in another thread.
setCanPlay(false); // Executed while the for loop is running
That would start and end the playing instantly.
Multithreading is the only way to stop an executing program (from the outside).

Timestamp, timers, time question

I've been Googling Java timestamps, timers, and anything to do with time and Java.
I just can't seem to get anything to work for me.
I need a timestamp to control a while loop like the pseudo-code below
while(true)
{
while(mytimer.millsecounds < amountOftimeIwantLoopToRunFor)
{
dostuff();
}
mytimer.rest();
}
Any ideas what data type I could use; I have tried Timestamp, but didn't seem to work.
Thanks
CiarĂ¡n
Do something like:
long maxduration = 10000; // 10 seconds.
long endtime = System.currentTimeMillis() + maxduration;
while (System.currentTimeMillis() < endtime) {
// ...
}
An (more advanced) alternative is using java.util.concurrent.ExecutorService. Here's an SSCCE:
package com.stackoverflow.q2303206;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String... args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 10, TimeUnit.SECONDS); // Get 10 seconds time.
executor.shutdown();
}
}
class Task implements Callable<String> {
public String call() throws Exception {
while (true) {
// ...
}
return null;
}
}

Categories

Resources