I m having a server code to process an image.
Now there are n number of requests which tries to execute the code which results in OutOfMemory error or the server to hang and the server goes to not responding state.
To stop the code from executing at once all the requests I m limiting to execute the code one at a time using the below method where i have a variable
if the variable is 10 then wait for the variable to come at 0
if at 0 then set it to 10 then execute the code
run the code and finally set i to 0
The code here -
static newa.Counter cn;
public int getCounta() {
return cn.getCount();
}
public void setCounta(int i) {
cn = new newa.Counter();
cn.setCount(i);
}
at the function i m doing this -
public BufferedImage getScaledImage(byte[] imageBytes)
{
int i=0;
Boolean b = false;
BufferedImage scaledImage = null;
newa.NewClass1 sc = new newa.NewClass1();
try {
sc.getCounta();
} catch (NullPointerException ne) {
sc.setCounta(0);
}
i = sc.getCounta();
if(i==0)
{
sc.setCounta(10);
b = true;
}
else
{
while( b == false)
{
try
{
Thread.sleep(2000);
i = sc.getCounta();
if( i==0)
{
sc.setCounta(10);
b = true;
System.out.println("Out of Loop");
}
} catch (InterruptedException ex) {
System.out.println("getScaledImage Thread exception: " + ex);
}
}
}
..... execute further code
try { } catch { } finally { sc.setCounta(0); }
}
Is there any way I can have this simplified using the Runnable interface or something as I don't know how to do multi-threading.
Forget about the counter and use a synchronized method. Changed your method head to this:
public synchronized BufferedImage getScaledImage(byte[] imageBytes)
This lets all the threads entering the method wait until no other thread is executing the method.
If you want only a small number of threads doing the processing you can use Executor framework to have a thread pool of 10 threads. This will ensure that at one time maximum of 10 threads will be processing the requests.
Related
So I have a function which looks like this
ExecutorService executorService = Executors.newFixedThreadPool(2000);
Boolean getMore = true;
try{
While (getMore) {
JSONObject response = getPaginatedResponse();
int[] ar = response.get("something");
if (ar.length > 0) {
// loop through the array and invoke executorService.submit() for each
}
else { getMore = false; }
}
executorService.shutdown();
try {
System.out.println("waiting for tasks to complete, termination starting at : "+java.time.LocalDateTime.now());
executorService.awaitTermination(15, TimeUnit.MINUTES);
} catch (InterruptedException e) {
throw new Exception("loading was interrupted... thread pool timed out!");
}
} catch (Exception) {
System.out.println("Fatal error");
}
My issue is that the each of these threads invoke x number of threads, which in turn each call an API and processes its response, the implementation stops execution after all the "First-level" threads gets fired, but not necessarily all the second level ones, which is crucial for my program, how or where can I invoke the executerService.shutdown() to make sure that all the threads were called.
you can put executorService.shutdown(); inside finally block of exception
I'm hoping some concurrency experts can advise as I'm not looking to rewrite something that likely exists.
Picture the problem; I have a web connection that comes calling looking for their unique computed result (with a key that they provide in order to retrieve their result) - however the result may not have been computed YET so I would like for the connection to wait (block) for UP TO n seconds before giving up and telling them I don't (yet) have their result (computation time to calculate value is non deterministic). something like;
String getValue (String key)
{
String value = [MISSING_PIECE_OF_PUZZLE].getValueOrTimeout(key, 10, TimeUnit.SECONDS)
if (value == null)
return "Not computed within 10 Seconds";
else
return "Value was computed and was " + value;
}
and then have another thread (the computation threads)that is doing the calculations - something like ;
public void writeValues()
{
....
[MISSING_PIECE_OF_PUZZLE].put(key, computedValue)
}
In this scenario, there are a number of threads working in the background to compute the values that will ultimately be picked up by a web connections. The web connections have NO control or authority over what is computed and when the computations execute - as I've said - this is being done in a pool in the background but these thread can publish when the computation has completed (how they do is the gist of this question). The publish message maybe consumed or not - depending if any subscribers are interested in this computed value.
As these are web connections that will be blocking - i could potentially have 1000s of concurrent connections waiting (subscribing) for their specific computed value so such a solution needs to be very light on blocking resources. The closest i've came to is this SO question which I will explore further but wanted to check i'm not missing something blindly obvious before writing this myself?
I think you should use a Future it gives an ability to compute data in a separate thread and block for the requested time period while waiting for an answer. Notice how it throws an exception if more then 3 seconds passed
public class MyClass {
// Simulates havy work that takes 10 seconds
private static int getValueOrTimeout() throws InterruptedException {
TimeUnit.SECONDS.sleep(10);
return 123;
}
public static void main(String... args) throws InterruptedException, ExecutionException {
Callable<Integer> task = () -> {
Integer val = null;
try {
val = getValueOrTimeout();
} catch (InterruptedException e) {
throw new IllegalStateException("task interrupted", e);
}
return val;
};
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<Integer> future = executor.submit(task);
System.out.println("future done? " + future.isDone());
try {
Integer result = future.get(3, TimeUnit.SECONDS);
System.out.print("Value was computed and was : " + result);
} catch (TimeoutException ex) {
System.out.println("Not computed within 10 Seconds");
}
}
}
After looking in changes in your question I wanted to suggest a different approach using BlockingQueue in such case the producer logic completely separated from the consumer so you could do something like this
public class MyClass {
private static BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
private static Map<String, String> dataComputed = new ConcurrentHashMap<>();
public static void writeValues(String key) {
Random r = new Random();
try {
// Simulate working for long time
TimeUnit.SECONDS.sleep(r.nextInt(11));
String value = "Hello there fdfsd" + Math.random();
queue.offer(value);
dataComputed.putIfAbsent(key, value);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static String getValueOrTimeout(String key) throws InterruptedException {
String result = dataComputed.get(key);
if (result == null) {
result = queue.poll(10, TimeUnit.SECONDS);
}
return result;
}
public static void main(String... args) throws InterruptedException, ExecutionException {
String key = "TheKey";
Thread producer = new Thread(() -> {
writeValues(key);
});
Thread consumer = new Thread(() -> {
try {
String message = getValueOrTimeout(key);
if (message == null) {
System.out.println("No message in 10 seconds");
} else {
System.out.println("The message:" + message);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
consumer.start();
producer.start();
}
}
With that said I have to agree with #earned that making the client thread to wait is not a good approach instead I would suggest using a WebSocket which gives you an ability to push data to the client when it is ready you can find lots of tutorials on WebSocket here is one for example ws tutorial
I'm reading a server log file after an event is performed on the UI. I have a while loop which waits for certain conditions to match and then returns that line of the log. Sometimes, however, there's a case where an event occurs before the code looks at the log and cannot get the new line. This causes the while loop to just hang and this hangs until another event occurs with the provided conditions. This is problematic for obvious reasons. Is there a way to break out of the while loop after a few seconds no matter what the case maybe? Following is my code
public String method(String, a, String b, String c) {
channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(a + "\n" + b);
channel.connect();
fromServer = new BufferedReader (new InputStreamReader(channel.getInputStream()));
String time = methodToFireAnEventInUI();
Thread.sleep(2000);
String x = null;
while (true){
x = fromServer.readLine();
if(!x.equals(null) && x.contains(c) && x.contains(time)){
break;
}
}
msg = x.toString();
}catch (Exception e){
e.printStackTrace();
}
closeConnection();
return msg;
}
If you look at the above code, it hangs right at "x = fromServer.readline();" and just doesn't go anywhere, and that is where I want the logic for it to wait for an x amount of time and just abort the loop after that.
My attempt of "thread.sleep" ahead of the while loop doesn't work either.
You can put this logic in a separate thread and use a while like this:
class TestThread extends Thread {
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
method();
}
}
public void method() {
try {
// this method hangs. You can replace it with your method
while (true) {
sleep(100);
}
} catch (Exception e) {
System.out.println("Thread is interrupted");
}
}
}
After that you can interrupt this thread if it takes longer than some time frame like this:
public static void main(String[] args) throws Exception {
TestThread t1 = new TestThread();
long startTime = System.currentTimeMillis();
t1.start();
long currentTime = System.currentTimeMillis();
while (currentTime - startTime < 5000) { // you can decide the desired interval
sleep(1000); // sleep some time
currentTime = System.currentTimeMillis();
System.out.println(currentTime); //print this to ensure that the program is still running
}
t1.interrupt(); //interrupt the thread
}
How about simply:
long timeOut = System.currentTimeMillis() + 5000; // change the value to what ever(millis)
while(System.currentTimeMillis() < timeOut){
// do whatever
}
As your while loop blocks at "x = fromServer.readline();" you can just share the reader instance to another thread and make that thread close the reader after timeout. This will cause your readLine to throw exception which you can handle and proceed.
Find answer here:
How do I measure time elapsed in Java?
Try the approach below:
long startTime = System.nanoTime(); //fetch starting time
while(true ||(System.nanoTime()-startTime)<200000)
{
// do something
}
I have a thread that copies a file and give the progress bar the progress, I have a method the stops the filestream copy and kills the thread, I am trying to implement a jOptionPanel yes_no to ask the user if they are sure they want to delete. But i need to be able to pause the fileInputStream copy until the thread either stops or is continued. The thread waits but the file copy keeps going. how can i fix this? Any help would be great
First is the thread I want to pause
thr = new Thread("cool") {
#Override
public void run() {
while (running == true) {
try {
newWorkFileName();
long length = fileIn.length();
long counter = 1;
int r;
byte[] b = new byte[1024];
fin = new FileInputStream(fileIn);
fout = new FileOutputStream(fileOut);
tvConvertInterface.updateJLabel2("Creating File");
while ((r = fin.read(b)) != -1) {
counter += r;
fout.write(b, 0, r);
prog = (int) Math.round(100 * counter / length);
tvConvertInterface.updateJProgressbar1(prog);
}
fin.close();
fout.close();
tvConvertInterface.disableStopBtn();
tvConvertInterface.updateJLabel2("Work File Created");
running = false;
} catch (NullPointerException | IOException ex) {
tvConvertInterface.disableStopBtn();
tvConvertInterface.updateJLabel2("File is not valid");
Logger.getLogger(TvConvertGutts.class.getName()).log(Level.SEVERE, null, ex);
tvConvertInterface.updateJProgressbar1(0);
running = false;
}
}
}
};
Next is the Method that i want to implement the jOptionPanel
public boolean terminate() throws IOException, InterruptedException {
synchronized (thr) {
thr.wait();//MAKES THREAD WAIT
//I NEED TO PAUSE THE FILESTREAM AND BE ABLE TO RESUME
}
int n = JOptionPane.showConfirmDialog(
null, "SURE YOU WANT TO DELETE?",
"Kill It Dude",
JOptionPane.YES_NO_OPTION);
if (n == JOptionPane.YES_OPTION) {
fin.close(); //CLOSE INPUT STREAM
fout.flush();//FLUSH OUTPUT STREAM
fout.close(); //CLOSE OUTPUT STREAM
thr.interrupt();//KIILL THE THREAD
System.out.println(thr.getState());//PRINT STATE OF THREAD
TvConvertInterface bst = new TvConvertInterface(null, true);
bst.disableStopBtn();//SET PROGRESSBAR TO 0
} else if (n == JOptionPane.NO_OPTION) {
synchronized (thr) {
thr.notify();//DONT DELETE AND CONTINUE
}
} else {
System.out.println("spewin");
}
return false;
}
This terminate method is called by a button click. From a class called TvConvertInterface
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
try {
check.terminate();
} catch (IOException ex) {
Logger.getLogger(TvConvertInterface.class.getName()).log(Level.SEVERE, null, ex);
}
You are using the JAVA concurrency API incorrectly.
The object.wait() will pause the current thread and the object in this case would serve as a monitor object.
What you need to do is the following:
define a boolean shouldPauseThread variable
the while loop should check for the value in this variable; if it is true you should wait on a monitor object
if the user approves the cancelling, then the thread should end its execution, so there needs to be a check for another variable boolean stopThread
if the user wants to continue with processing, you will just reset the shouldPauseThread variable and notify on the previously used monitor object
you need to handle all the transitions from the mentioned states
I have used two different approach to measure time of threads but result are not matching
**Public void Main()**
{
Timer timer = new Timer();
int timetotal;
timer.start();
int numberOfThreads=5;
ExecutorService pool= Executors.newFixedThreadPool(numberOfThreads);
List<Future<Boolean>> futureList = new ArrayList<Future<Boolean>>();
Set<ReadProcess_MongoDB> callList = new HashSet<ReadProcess_MongoDB>();
CompletionService<ReadProcess_MongoDB> taskCompletionService;
taskCompletionService = new ExecutorCompletionService<ReadProcess_MongoDB>(pool);
Collection<Callable<ReadProcess_MongoDB>> list;
list = new LinkedList<Callable<ReadProcess_MongoDB>>();
for(int i=0;i<numberOfThreads;i++)
list.add((Callable<ReadProcess_MongoDB>) new ReadProcess_MongoDB(i));
try {
for (Callable<ReadProcess_MongoDB> callable : list) {
taskCompletionService.submit(callable);
}
for (int i = 0; i < list.size(); i++) {
Future<ReadProcess_MongoDB> result = taskCompletionService.take();
}
} catch (InterruptedException e) {
// no real error handling. Don't do this in production!
e.printStackTrace();
} catch (ExecutionException e) {
// no real error handling. Don't do this in production!
e.printStackTrace();
}
finally {
pool.shutdown();
System.out.println("Done :)");
timer.stop();
System.out.println("Total consumed Time"+ timer.elapsed());
}
Other time I put in Call method()
**public String call()**
{
Timer timer = new Timer();
int timetotal;
timer.start();
DBCursor cursor = coll.find(whereQuery);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(ReadProcess_MongoDB.class.getName()).log(Level.SEVERE, null, ex);
}
timer.stop();
usedTimeForQueryProcess = timer.elapsed();
System.out.println("Thread Number="+this.threadNumber+ " MongoDB_readQuery used time "+usedTimeForQueryProcess);
System.out.println("runing.....");
return Objects.toString(usedTimeForQueryProcess);
}
In call Function, system print time of every thread and in Main function only display totaltime.Here I try check manually ,but both time are not matching .But bigger problem is Main function show less time than total time of all threads(Call function).
I have also tried to return used time from Call function But it is also create problem convert to long (especially runtime problem ).
Time of Both function
Main function time =289
Call function time=510(5 thread).
Would please somebody expain why this happening and how i can make right measurement ?
The Main time is lower than the total of each of your jobs because they are running in parallel. If you reduce your thread pool size down to 1 then you will the numbers be more like what you expect.
This is one of the benefits of doing multithreaded programming, getting more work done in less time than if it were done sequentially.