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.
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();
}
}
}
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.
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) {
I have a program that performs lots of calculations and reports them to a file frequently. I know that frequent write operations can slow a program down a lot, so to avoid it I'd like to have a second thread dedicated to the writing operations.
Right now I'm doing it with this class I wrote (the impatient can skip to the end of the question):
public class ParallelWriter implements Runnable {
private File file;
private BlockingQueue<Item> q;
private int indentation;
public ParallelWriter( File f ){
file = f;
q = new LinkedBlockingQueue<Item>();
indentation = 0;
}
public ParallelWriter append( CharSequence str ){
try {
CharSeqItem item = new CharSeqItem();
item.content = str;
item.type = ItemType.CHARSEQ;
q.put(item);
return this;
} catch (InterruptedException ex) {
throw new RuntimeException( ex );
}
}
public ParallelWriter newLine(){
try {
Item item = new Item();
item.type = ItemType.NEWLINE;
q.put(item);
return this;
} catch (InterruptedException ex) {
throw new RuntimeException( ex );
}
}
public void setIndent(int indentation) {
try{
IndentCommand item = new IndentCommand();
item.type = ItemType.INDENT;
item.indent = indentation;
q.put(item);
} catch (InterruptedException ex) {
throw new RuntimeException( ex );
}
}
public void end(){
try {
Item item = new Item();
item.type = ItemType.POISON;
q.put(item);
} catch (InterruptedException ex) {
throw new RuntimeException( ex );
}
}
public void run() {
BufferedWriter out = null;
Item item = null;
try{
out = new BufferedWriter( new FileWriter( file ) );
while( (item = q.take()).type != ItemType.POISON ){
switch( item.type ){
case NEWLINE:
out.newLine();
for( int i = 0; i < indentation; i++ )
out.append(" ");
break;
case INDENT:
indentation = ((IndentCommand)item).indent;
break;
case CHARSEQ:
out.append( ((CharSeqItem)item).content );
}
}
} catch (InterruptedException ex){
throw new RuntimeException( ex );
} catch (IOException ex) {
throw new RuntimeException( ex );
} finally {
if( out != null ) try {
out.close();
} catch (IOException ex) {
throw new RuntimeException( ex );
}
}
}
private enum ItemType {
CHARSEQ, NEWLINE, INDENT, POISON;
}
private static class Item {
ItemType type;
}
private static class CharSeqItem extends Item {
CharSequence content;
}
private static class IndentCommand extends Item {
int indent;
}
}
And then I use it by doing:
ParallelWriter w = new ParallelWriter( myFile );
new Thread(w).start();
/// Lots of
w.append(" things ").newLine();
w.setIndent(2);
w.newLine().append(" more things ");
/// and finally
w.end();
While this works perfectly well, I'm wondering:
Is there a better way to accomplish this?
Your basic approach looks fine. I would structure the code as follows:
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public interface FileWriter {
FileWriter append(CharSequence seq);
FileWriter indent(int indent);
void close();
}
class AsyncFileWriter implements FileWriter, Runnable {
private final File file;
private final Writer out;
private final BlockingQueue<Item> queue = new LinkedBlockingQueue<Item>();
private volatile boolean started = false;
private volatile boolean stopped = false;
public AsyncFileWriter(File file) throws IOException {
this.file = file;
this.out = new BufferedWriter(new java.io.FileWriter(file));
}
public FileWriter append(CharSequence seq) {
if (!started) {
throw new IllegalStateException("open() call expected before append()");
}
try {
queue.put(new CharSeqItem(seq));
} catch (InterruptedException ignored) {
}
return this;
}
public FileWriter indent(int indent) {
if (!started) {
throw new IllegalStateException("open() call expected before append()");
}
try {
queue.put(new IndentItem(indent));
} catch (InterruptedException ignored) {
}
return this;
}
public void open() {
this.started = true;
new Thread(this).start();
}
public void run() {
while (!stopped) {
try {
Item item = queue.poll(100, TimeUnit.MICROSECONDS);
if (item != null) {
try {
item.write(out);
} catch (IOException logme) {
}
}
} catch (InterruptedException e) {
}
}
try {
out.close();
} catch (IOException ignore) {
}
}
public void close() {
this.stopped = true;
}
private static interface Item {
void write(Writer out) throws IOException;
}
private static class CharSeqItem implements Item {
private final CharSequence sequence;
public CharSeqItem(CharSequence sequence) {
this.sequence = sequence;
}
public void write(Writer out) throws IOException {
out.append(sequence);
}
}
private static class IndentItem implements Item {
private final int indent;
public IndentItem(int indent) {
this.indent = indent;
}
public void write(Writer out) throws IOException {
for (int i = 0; i < indent; i++) {
out.append(" ");
}
}
}
}
If you do not want to write in a separate thread (maybe in a test?), you can have an implementation of FileWriter which calls append on the Writer in the caller thread.
One good way to exchange data with a single consumer thread is to use an Exchanger.
You could use a StringBuilder or ByteBuffer as the buffer to exchange with the background thread. The latency incurred can be around 1 micro-second, doesn't involve creating any objects and which is lower using a BlockingQueue.
From the example which I think is worth repeating here.
class FillAndEmpty {
Exchanger<DataBuffer> exchanger = new Exchanger<DataBuffer>();
DataBuffer initialEmptyBuffer = ... a made-up type
DataBuffer initialFullBuffer = ...
class FillingLoop implements Runnable {
public void run() {
DataBuffer currentBuffer = initialEmptyBuffer;
try {
while (currentBuffer != null) {
addToBuffer(currentBuffer);
if (currentBuffer.isFull())
currentBuffer = exchanger.exchange(currentBuffer);
}
} catch (InterruptedException ex) { ... handle ... }
}
}
class EmptyingLoop implements Runnable {
public void run() {
DataBuffer currentBuffer = initialFullBuffer;
try {
while (currentBuffer != null) {
takeFromBuffer(currentBuffer);
if (currentBuffer.isEmpty())
currentBuffer = exchanger.exchange(currentBuffer);
}
} catch (InterruptedException ex) { ... handle ...}
}
}
void start() {
new Thread(new FillingLoop()).start();
new Thread(new EmptyingLoop()).start();
}
}
Using a LinkedBlockingQueue is a pretty good idea. Not sure I like some of the style of the code... but the principle seems sound.
I would maybe add a capacity to the LinkedBlockingQueue equal to a certain % of your total memory.. say 10,000 items.. this way if your writing is going too slow, your worker threads won't keep adding more work until the heap is blown.
I know that frequent write operations
can slow a program down a lot
Probably not as much as you think, provided you use buffering.