Good day to all of you .
I have a Thread as shown below , which in its while true condition , continuously checks data inside a HashSet , if it present it extracts those and does something and incase there were no symbols for 5 minutes in HashSet (here is my question how can i keep such a condition in below else block is that possible )
package com;
import java.util.HashSet;
public class Tester extends Thread
{
HashSet<String> set = new HashSet<String>();
public void run() {
while (true) {
try {
if (set.size() > 0) {
// extract those and do something
set.clear();
}
else {
// if there were no elements in set for more than 5 minutes than execute a task
// here is my question , to keep such a check is possible or not
}
Thread.sleep(2000);
} catch (Exception e) {
}
}
}
public static void main(String args[]) {
try {
Tester qT = new Tester();
qT.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
You can initialize a timestamp before your loop. Then, if set.size() > 0 is true, you update the timestamp to the current time. In the else you check whether the saved timestamp is at least 5 minutes older than the current timestamp.
You probably want something like this:
package com;
import java.util.HashSet;
import java.util.Date;
public class Tester extends Thread
{
HashSet<String> set = new HashSet<String>();
public void run() {
Date d = new Date();
while (true) {
try {
if (set.size() > 0) {
d = new Date();
set.clear();
}
else {
if(new Date().getTime() - d.getTime() > 300000){
d = new Date();
//execute your method
}
}
Thread.sleep(2000);
} catch (Exception e) {
}
}
}
public static void main(String args[]) {
try {
Tester qT = new Tester();
qT.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
First, create a timer:
Timer timer = new Timer(300000, new ActionListener() {
public void actionPerformed(ActionEvent event) {
<preform the task here>
}
});
timer.setRepeats(false);
When the thread starts, start the timer:
timer.start();
If there are items in the set:
timer.restart();
There is no need for an else, the timer takes care of that. You should check timer.isRunning in the main loop condition so the checks for set elements stop after 5 minutes.
When the thread enters run , get the SystemTime . Also get the current time in else block as shown below: Also in case we get data from hashset just compute the new system time t1
package com;
import java.util.HashSet;
public class Tester extends Thread
{
HashSet<String> set = new HashSet<String>();
public void run() {
long t1 = date.getTime();
while (true) {
try {
if (set.size() > 0) {
// extract those and do something
set.clear();
}
else {
// if there were no elements in set for more than 5 minutes than execute a task
// here is my question , to keep such a check is possible or not
long t1 = date.getTime();
if(!hashset_data_not_available)
{
t1 = date.getTime();
}
if((t2-t1)/(60*1000)>5 && if_hashset_data_not_available) {
//do something that u wanna do
{
}
Thread.sleep(2000);
} catch (Exception e) {
Related
I need your help. I should use the java.util.concurrent package in my exercise but I don't know how to do it. The question is only about the get method.
public String getInput() {
if (inputList.isEmpty()) return null;
String input = inputList.get(0);
inputList.remove(0);
return input;
}
How do I need to write the code to wait till the given list (variable: inputList) becomes non-empty?
Greetings
you could try using the LinkedBlockingDeque class from the java.util.concurrent
package which implements the BlockingDequeinterface.
it lets you add items to the BlockingDeque and the take* methods block until there is an element available and remove it after fetching. Have a look at the Javadoc
Here is an example:
public class Queue {
BlockingDeque<String> inputList = new LinkedBlockingDeque<>();
public String getInput() {
try {
System.out.println("waiting on queue");
String input = inputList.takeFirst();
System.out.println("taken " + input);
return input;
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
Queue queue = new Queue();
new Thread(() -> {
try {
Thread.sleep(4000);
queue.inputList.add("string");
System.out.println("added string");
Thread.sleep(2000);
queue.inputList.add("string1");
System.out.println("added string 1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
for (int i = 0; i < 2; i++){
queue.getInput();
}
}
}
Hi I'm a newbie to concurrency so I wrote a very basic program to see whether on a threads completion the future.isDone() method shows true, unfortunately it always shows "false" when I schedule the task with scheduledAtFixedRate method. However if I use schedule method it shows "true" of course the simple task does not rerun seconds later. Any suggestions or explanations to help me understand why this is the case would be much appreciated.
Thanks!
Here with the code:
package com.company;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) {
Main mn = new Main();
System.out.println("Main thread started...");
mn.runobjects();
System.out.println("Main thread stopping...");
}
#Test
public void runobjects(){
List<commonrun> Obj = new ArrayList<>();
Obj.add(new TestObj1());
Obj.add(new TestObj2());
Obj.add(new TestObj3());
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
ScheduledFuture<?> futures1 = null;
ScheduledFuture<?> futures2 = null;
ScheduledFuture<?> futures3 = null;
int i=0;
for (commonrun obj : Obj){
if (i==0) {
futures1 = executor.schedule(() -> obj.runme(), 0, TimeUnit.SECONDS);
}
if (i==1) {
futures2 = executor.scheduleAtFixedRate(() -> obj.runme(), 0, 10, TimeUnit.SECONDS);
}
if (i==2) {
futures3 = executor.scheduleAtFixedRate(() -> obj.runme(), 0, 10, TimeUnit.SECONDS);
}
i++;
}
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 1 is done : "+ futures1.isDone());
System.out.println("Thread 2 is done : "+ futures2.isDone());
System.out.println("Thread 3 is done : "+ futures3.isDone());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.company;
public interface commonrun {
public void runme();
}
package com.company;
public class TestObj1 implements commonrun {
static int counter = 0;
#Override
public void runme() {
System.out.println("Object 1 Starting... run : " + counter);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Object 1 Stopping... run : " + counter);
counter++;
}
}
package com.company;
public class TestObj2 implements commonrun {
#Override
public void runme() {
System.out.println("Object 2 Starting...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Object 2 Stopping...");
}
}
package com.company;
public class TestObj3 implements commonrun {
#Override
public void runme() {
System.out.println("Object 3 Starting...");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Object 3 Stopping...");
}
}
ScheduledExecutorService.scheduleAtFixedRate() schedules repetitive task. It will never (naturally) finish, so it won't become done. From method's documentation:
the task will only terminate via cancellation or termination of the
executor
Thus, only if you call future.cancel() or executor.terminate() will the task become done and future.isDone() will then return true.
While one could potentially expect that future becomes done as soon as first task's execution completes, this is not the case for the following reasons:
once future becomes done it cannot be "undone" ("done" is a terminal state for a future), so isDone cannot report current execution state of a repetitive job
once future becomes done it makes no sense to cancel it (there isn't anything to cancel) -- that would not fit a repetitive task, which won't run indefinitely until canceled.
I have a multi-threaded command line app. It is a web service client with a pool of 10 threads that churns away, sending requests, batch-style, to a server.
But it runs for a few days, and sometimes further down the pipeline, the queues start getting backed up. So I want to go to the client, press - or + and have that increase or decrease a Thread.sleep(waitingTime), to take pressure off the server.
I tried running a Scanner in a separate thread, but it didn't seem to work. Has anyone managed to get non-blocking I/O working in Java? I presume it's possible, but I'm giving up for now.
Edit: Added test code as per request
package test;
import java.io.*;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by djb on 2015/06/03.
*/
public class ThreadTest {
public ThreadTest() {
}
static long rand = 10000;
public static void main(String args[])
{
ExecutorService executor = Executors.newFixedThreadPool(5);
File f = new File("C:\\code\\ThreadTest\\text.csv");
try {
Runnable keyPressThread = new ThreadTest.KeyPressThread();
Thread t = new Thread(keyPressThread);
t.start();
BufferedReader br = new BufferedReader(new FileReader(f));
String line;
while ((line = br.readLine()) != null)
{
try {
final String copy = line;
executor.execute(new Runnable() {
#Override
public void run() {
try {
System.out.println(rand);
Thread.sleep(rand);
System.out.println(copy);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
} catch (Exception e)
{
e.printStackTrace();
}
}
} catch (Exception e)
{
e.printStackTrace();
}
}
public static class KeyPressThread implements Runnable {
Scanner inputReader = new Scanner(System.in);
//Method that gets called when the object is instantiated
public KeyPressThread() {
}
public void run() {
String input = inputReader.next();
if (input.equals("["))
{
rand+=100;
System.out.println("Pressed [");
}
if (input.equals("]"))
{
rand-=100;
System.out.println("Pressed ]");
}
}
}
}
Your KeyPressThread is only testing once:
This will make it watch constantly.
public void run()
{
while(true)
{
if (inputReader.hasNext())
{
String input = inputReader.next();
if (input.equals("["))
{
rand+=100;
System.out.println("Pressed [");
}
if (input.equals("]"))
{
rand-=100;
System.out.println("Pressed ]");
}
if (input.equalsIgnoreCase("Q"))
{
break; // stop KeyPressThread
}
}
}
}
System.in is line buffered, by default. This means that no input is actually passed to the program until you press ENTER.
I'm trying to implement a mechanism that deletes cached files when the objects that hold them die, and decided to use PhantomReferences to get notified on garbage collection of an object. The problem is I keep experiencing weird behavior of the ReferenceQueue. When I change something in my code it suddenly doesn't fetch objects anymore. So I tried to make this example for testing, and ran into the same problem:
public class DeathNotificationObject {
private static ReferenceQueue<DeathNotificationObject>
refQueue = new ReferenceQueue<DeathNotificationObject>();
static {
Thread deathThread = new Thread("Death notification") {
#Override
public void run() {
try {
while (true) {
refQueue.remove();
System.out.println("I'm dying!");
}
} catch (Throwable t) {
t.printStackTrace();
}
}
};
deathThread.setDaemon(true);
deathThread.start();
}
public DeathNotificationObject() {
System.out.println("I'm born.");
new PhantomReference<DeathNotificationObject>(this, refQueue);
}
public static void main(String[] args) {
for (int i = 0 ; i < 10 ; i++) {
new DeathNotificationObject();
}
try {
System.gc();
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The output is:
I'm born.
I'm born.
I'm born.
I'm born.
I'm born.
I'm born.
I'm born.
I'm born.
I'm born.
I'm born.
Needless to say, changing the sleep time, calling gc multiple times etc. didn't work.
UPDATE
As suggested, I called Reference.enqueue() of my reference, which solved the problem.
The weird thing, is that I have some code that works perfectly (just tested it), although it never calls enqueue. Is it possible that putting the Reference into a Map somehow magically enqueued the reference?
public class ElementCachedImage {
private static Map<PhantomReference<ElementCachedImage>, File>
refMap = new HashMap<PhantomReference<ElementCachedImage>, File>();
private static ReferenceQueue<ElementCachedImage>
refQue = new ReferenceQueue<ElementCachedImage>();
static {
Thread cleanUpThread = new Thread("Image Temporary Files cleanup") {
#Override
public void run() {
try {
while (true) {
Reference<? extends ElementCachedImage> phanRef =
refQue.remove();
File f = refMap.remove(phanRef);
Calendar c = Calendar.getInstance();
c.setTimeInMillis(f.lastModified());
_log.debug("Deleting unused file: " + f + " created at " + c.getTime());
f.delete();
}
} catch (Throwable t) {
_log.error(t);
}
}
};
cleanUpThread.setDaemon(true);
cleanUpThread.start();
}
ImageWrapper img = null;
private static Logger _log = Logger.getLogger(ElementCachedImage.class);
public boolean copyToFile(File dest) {
try {
FileUtils.copyFile(img.getFile(), dest);
} catch (IOException e) {
_log.error(e);
return false;
}
return true;
}
public ElementCachedImage(BufferedImage bi) {
if (bi == null) throw new NullPointerException();
img = new ImageWrapper(bi);
PhantomReference<ElementCachedImage> pref =
new PhantomReference<ElementCachedImage>(this, refQue);
refMap.put(pref, img.getFile());
new Thread("Save image to file") {
#Override
public void run() {
synchronized(ElementCachedImage.this) {
if (img != null) {
img.saveToFile();
img.getFile().deleteOnExit();
}
}
}
}.start();
}
}
Some filtered output:
2013-08-05 22:35:01,932 DEBUG Save image to file: <>\AppData\Local\Temp\tmp7..0.PNG
2013-08-05 22:35:03,379 DEBUG Deleting unused file: <>\AppData\Local\Temp\tmp7..0.PNG created at Mon Aug 05 22:35:02 IDT 2013
The answer is, that in your example the PhantomReference itself is unreachable and hence garbage collected before the referred object itself is garbage collected. So at the time the object is GCed there is no more Reference and the GC does not know that it should enqueue something somewhere.
This of course is some kind of head-to-head race :-)
This also explains (without looking to deep into your new code) why putting the reference into some reachable collection makes the example work.
Just for reference (pun intended) here is a modified version of your first example which works (on my machine :-) I just added a set holding all references.
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.HashSet;
import java.util.Set;
public class DeathNotificationObject {
private static ReferenceQueue<DeathNotificationObject> refQueue = new ReferenceQueue<DeathNotificationObject>();
private static Set<Reference<DeathNotificationObject>> refs = new HashSet<>();
static {
Thread deathThread = new Thread("Death notification") {
#Override
public void run() {
try {
while (true) {
Reference<? extends DeathNotificationObject> ref = refQueue.remove();
refs.remove(ref);
System.out.println("I'm dying!");
}
} catch (Throwable t) {
t.printStackTrace();
}
}
};
deathThread.setDaemon(true);
deathThread.start();
}
public DeathNotificationObject() {
System.out.println("I'm born.");
PhantomReference<DeathNotificationObject> ref = new PhantomReference<DeathNotificationObject>(this, refQueue);
refs.add(ref);
}
public static void main(String[] args) {
for (int i = 0 ; i < 10 ; i++) {
new DeathNotificationObject();
}
try {
System.gc();
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Update
Calling enqueue by hand is possible in your example but not in real code. it gives plain wrong result. Let me show by calling enqueue in the constructor and using another main:
public DeathNotificationObject() {
System.out.println("I'm born.");
PhantomReference<DeathNotificationObject> ref = new PhantomReference<DeathNotificationObject>(this, refQueue);
ref.enqueue();
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0 ; i < 5 ; i++) {
DeathNotificationObject item = new DeathNotificationObject();
System.out.println("working with item "+item);
Thread.sleep(1000);
System.out.println("stopped working with item "+item);
// simulate release item
item = null;
}
try {
System.gc();
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The output will be like this:
I'm born.
I'm dying!
working with item DeathNotificationObject#6908b095
stopped working with item DeathNotificationObject#6908b095
Which means that whatever you wanted to do with the reference queue would be done when the item is still alive.
I have this piece of code inside my application which runs continuously .
When ever a symbol is added , this below Thread gets fired up and executes two different tasks ( currently the task is represented as sys out for simplicity )
For the first time everything runs fine , but from the second time , the task is being repeated for all the symbols present inside the allSymbolsSet .
The issue i am facing here is that i want to run the task only for the new symbol added . (For example if the allSymbolsSet consists of 3 symbols initially and when a new symbol is added to it , it runs that task for all the 4 symbols , whereas i want it to execute it only for the newly added symbol )
This is my code
package com;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.PriorityBlockingQueue;
public class TaskerThread extends Thread {
private PriorityBlockingQueue<String> priorityBlocking = new PriorityBlockingQueue<String>();
private Set<String> allSymbolsSet = new HashSet<String>();
public void addSymbols(String str) {
if (str != null) {
priorityBlocking.add(str);
}
}
public void run() {
while (true) {
try {
boolean added = false;
while (priorityBlocking.peek() != null) {
added = true;
String symbol = priorityBlocking.poll();
allSymbolsSet.add(symbol);
try {
System.out.println("Symbol From priorityBlocking"+ " " + symbol);
} catch (Exception e) {
e.printStackTrace();
}
}
Iterator<String> ite = allSymbolsSet.iterator();
if (added) {
while (ite.hasNext()) {
String symbol = ite.next();
if (symbol != null && symbol.trim().length() > 0) {
try {
System.out.println("Symbol From allSymbolsSet"+ " " + symbol);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) {
try {
TaskerThread qT = new TaskerThread();
qT.start();
qT.addSymbols("SymbolTest");
Thread.sleep(110);
qT.addSymbols("Symbo2222222");
} catch (Exception e) {
e.printStackTrace();
}
}
}
add() method returns false if the Object being added was ignored because it was already present
A simple solution would be to have two hashsets - set1, holding all symbols, set2 containing newly added symbols. Add new symbols to set2, in your thread's run, when the execution is complete, add new symbol to set1 and remove it from set2. How about that?
Well, of course it runs for all elements in the set, you are iterating over them!
package com;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.PriorityBlockingQueue;
public class TaskerThread extends Thread {
private final PriorityBlockingQueue<String> priorityBlocking = new PriorityBlockingQueue<String>();
private final Set<String> allSymbolsSet = new Collections.synchronizedSet(new HashSet<String>());
public void addSymbols(String str) {
if (str != null) {
priorityBlocking.add(str);
}
}
public void run() {
while (true) {
try {
while (true) {
final String symbol = priorityBlocking.take();
if (allSymbolsSet.add(symbol)) {
doSomething(symbol); // do whatever you want with the symbol
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) {
try {
TaskerThread qT = new TaskerThread();
qT.start();
qT.addSymbols("SymbolTest");
} catch (Exception e) {
e.printStackTrace();
}
}
}
This should do what you were looking for. Take better care of possible exceptions, namely InterruptedException.