I am submitting Callables to an ExecutorCompletionService and it seems like the submit() method does not block code while submitting Callables. Here is the code that I have:
ExecutorService executor = Executors.newFixedThreadPool(30);
BlockingQueue<Future<Data>> completionQueue = new LinkedBlockingQueue();
ExecutorCompletionService<Data> completionService = new ExecutorCompletionService<Data>(executor, completionQueue);
while(receivingPackets) {
Callable<Data> splitPacketCallable = new SplitPacket(packetString);
completionService.submit(splitPacketCallable);
try {
// Allow submit to finish
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException ex) {
System.out.println("Something went wrong with sleeping");
}
try {
Future<Data> dataFuture = completionService.poll();
if (dataFuture != null) {
Data data = dataFuture.get();
fileWriter.writeLine(data.toString());
}
} catch (InterruptedException ex) {
System.out.println("Error from poll: " + ex.toString());
} catch (ExecutionException ex) {
System.out.println("Error from get: " + ex.toString());
}
}
// Finish any remaining threads
while (!completionQueue.isEmpty()) {
try {
Future<Data> dataFuture = completionService.take();
Data data = dataFuture.get();
fileWriter.writeLine(data.toString());
} catch (InterruptedException ex) {
System.out.println("Error from take: " + ex.toString());
} catch (ExecutionException ex) {
System.out.println("Error from get: " + ex.toString());
}
}
fileWriter.close();
executor.shutdown();
A few things to note:
Data is a class that stores data in a special format. SplitPacket is a class that implements Callable that takes in a String that has arrived and splits it into chunks to be saved in Data. fileWriter and its method writeLine is a Runnable Class that will asynchronously write to a single file from multiple threads.
If I play with the sleep in the for loop, I start getting inconstant results in my output file. If I sleep for 50 ms every time I submit a Callable, everything works perfectly. However, if I submit with a low value (say 0-5 ms), I start getting dropped threads in the output. To me, this implies that the submit() method of ExecutorCompletionService does not block. However, because blocking a submitted callable seems vital, I also assume I am just implementing this wrong.
In my case, I don't know how many packets will be coming in so I need to be able to continuously add Callables to the Executor. I have tried this with a for loop instead of a while loop so that I can send a given number of packets and see if they get printed on the other end, and I can only get them to go through if I have a delay after submit.
Is there a way to fix this without adding a hack-y delay?
If you look at the source of ExecutorCompletionService you will see that the Futures are being added to completionQueue after the task is marked as done.
private class QueueingFuture extends FutureTask<Void> {
QueueingFuture(RunnableFuture<V> task) {
super(task, null);
this.task = task;
}
protected void done() { completionQueue.add(task); }
private final Future<V> task;
}
You may have an empty queue but still running tasks.
The simplest thing you can do is just count the tasks.
int count = 0;
while(receivingPackets) {
...
completionService.submit(splitPacketCallable);
++count;
...
try {
Future<Data> dataFuture = completionService.poll();
if (dataFuture != null) {
--count;
...
}
...
}
// Finish any remaining threads
while (count-- > 0) {
...
}
Related
I have a java 8 based project which performs a certain function on a url. I need to modify the code snippet below so that it is capable of killing the thread/process running and run the next instance after a certain period of time irrespective of current process status.
I tried the following techniques to implement the thread kill procedure:
Executor service
Timer Task
Multithreaded thread kill
The code snippet for my most recent attempt is linked below.
#SuppressWarnings("static-access")
public static void main(String[] args) {
//fetch url from the txt file
List<String> careerUrls = getCareerUrls();
int a = 0;
DBConnection ds = null;
ds = DBConnection.getInstance();
try (java.sql.Connection con = ds.getConnection()) {
//read a single Url
for (String url : careerUrls) {
int c = a++;
ExecutorService executor = Executors.newFixedThreadPool(3);
Future<?> future = executor.submit(new Runnable() {
#Override
// <-- job processing
public void run() {
long end_time = System.currentTimeMillis() + 10000;
System.out.println("STARTED PROCESSING URL: " + url);
jobareaDeciderSample w = new jobareaDeciderSample();
w.mainSample(url, c, con);
}
});
// <-- reject all further submissions
executor.shutdown();
try {
future.get(120, TimeUnit.SECONDS); // <-- wait 2 Minutes to finish
} catch (InterruptedException e) { // <-- possible error cases
System.out.println("job was interrupted");
future.cancel(true);
Thread.currentThread().interrupt();
;
} catch (ExecutionException e) {
System.out.println("caught exception: " + e.getCause());
} catch (TimeoutException e) {
System.out.println("timeout");
future.cancel(true);
}
// wait all unfinished tasks for 2 sec
if (!executor.awaitTermination(0, TimeUnit.SECONDS)) {
// force them to quit by interrupting
executor.shutdownNow();
}
}
} catch (Exception e) {
LOGGER.error(e);
}
}
You are correct with your approach.
calling cancel(true); on future is the right way to stop this task.
You have another problem- you cannot just stop a thread. (well you can, using stop() in thread class, but you should never do this).
cancel(true); sends information to the thread, that it should be stopped. Some java classes are responding to this information and throw interrupted exception. But some dont. You have to modify your task code, to check if Thread.currentThread().isInterrupted(), and if so, stop execution.
This is something you have to do in your code, which you call by
jobareaDeciderSample w = new jobareaDeciderSample();
w.mainSample(url, c, con);
You should do this in some long time spinning code, if you said you do some stuff with url, you should do it in your while loop, where you download information for the web. In other words, do this check only when your code spends 99% of the time.
Also you are calling
Thread.currentThread().interrupt();
in your main thread, this does not do anything for you, as if you want to quit current thread, you can just call return
I have a Producer-Consumer problem to implement in Java, where I want the producer thread to run for a specific amount of time e.g. 1 day, putting objects in a BlockingQueue -specifically tweets, streamed from Twitter Streaming API via Twitter4j- and the consumer thread to consume these objects from the queue and write them to file. I've used the PC logic from Read the 30Million user id's one by one from the big file, where producer is the FileTask and consumer is the CPUTask (check first answer; my approach uses the same iterations/try-catch blocks with it). Of course I adapted the implementations accordingly.
My main function is:
public static void main(String[] args) {
....
final int threadCount = 2;
// BlockingQueue with a capacity of 200
BlockingQueue<Tweet> tweets = new ArrayBlockingQueue<>(200);
// create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(threadCount);
Future<?> f = service.submit(new GathererTask(tweets));
try {
f.get(1,TimeUnit.MINUTES); // Give specific time to the GathererTask
} catch (InterruptedException | ExecutionException | TimeoutException e) {
f.cancel(true); // Stop the Gatherer
}
try {
service.submit(new FileTask(tweets)).get(); // Wait til FileTask completes
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
service.shutdownNow();
try {
service.awaitTermination(7, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Now, the problem is that, although it does stream the tweets and writes them to file, it never terminates and never gets to the f.cancel(true) part. What should I change for it to work properly? Also, could you explain in your answer what went wrong here with the thread logic, so I learn from my mistake? Thank you in advance.
These are the run() functions of my PC classes:
Producer:
#Override
public void run() {
StatusListener listener = new StatusListener(){
public void onStatus(Status status) {
try {
tweets.put(new Tweet(status.getText(),status.getCreatedAt(),status.getUser().getName(),status.getHashtagEntities()));
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentTread.interrupt(); // Also tried this command
}
}
public void onException(Exception ex) {
ex.printStackTrace();
}
};
twitterStream.addListener(listener);
... // More Twitter4j commands
}
Consumer:
public void run() {
Tweet tweet;
try(PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("out.csv", true)))) {
while(true) {
try {
// block if the queue is empty
tweet = tweets.take();
writeTweetToFile(tweet,out);
} catch (InterruptedException ex) {
break; // GathererTask has completed
}
}
// poll() returns null if the queue is empty
while((tweet = tweets.poll()) != null) {
writeTweetToFile(tweet,out);
}
} catch (IOException e) {
e.printStackTrace();
}
}
You should check if your Thread classes are handling the InterruptedException, if not, they will wait forever. This might help.
I tried to use multiple threads, sadly no luck:
public synchronized boolean pingServer(final String ip, final short port) {
final boolean[] returnbol = new boolean[1];
Thread tt = new Thread(new Runnable() {
#Override
public void run() {
try {
Socket s = new Socket(ip, port);
s.close();
returnbol[0] = true;
} catch (IOException e) {
returnbol[0] = false;
}
}
});
tt.start();
try {
tt.join();
} catch (InterruptedException e) {
tt.stop();
}
tt.stop();
return returnbol[0];
}
The main thread still Freezes for some reason.
Is there a "lagless" way to ping a server?
What exactly did you want to got in
try {
tt.join();
} catch (InterruptedException e) {
tt.stop();
}
block?
Here you joined to parallel thread and waits till this thread will ends (got ping result).
You have next options:
Wait till ping ends
Don't wait... and don't got result
Use some concurrency classes like Future<> to got result (but you will block thread at moment you ask result if it not retrieved yet)
Or you can use some 'callback' function/interface to threw result from inner 'ping' thread.
You will need to remove the following lines from your code.
The tt.join() will force the main thread to wait for tt to finish.
try {
tt.join();
} catch (InterruptedException e) {
tt.stop();
}
tt.stop();
Use a Future instead to get the result for later use
The application I'm maintaining (passed through many coders) has the Producer-Consumer problematic implemented using wait/notify mechanism.
Consumer waits for the message on the "server" side of the application and then forwards the message on the "client" side towards the LDAP server.
Problem is when multiple connections are established/terminated. The Producer threads just keep multiplicating and never get terminated when they should.
When a connection is terminated both the Producer/Consumer threads should be terminated as well.
With a high number of established/terminated connections, memory usage gets monstrous.
The code:
class Producer extends Thread {
public void run() {
long previous = 0;
long last = 0;
long sleeptime = 1;
while (alive) {
try{
last = System.currentTimeMillis();
byte[] aux;
if ((aux = cliente.readmessage()) != null){
sleeptime = 1;
previous = last;
synchronized (list) {
while (list.size() == MAX)
try {
list.wait();
} catch (InterruptedException ex) {
}
list.addFirst(new Messagetimestamped(aux, System
.currentTimeMillis()));
list.notifyAll();
}
}
else{
if (last-previous > 1000)
sleeptime = 1000;
else
sleeptime = 1;
sleep(sleeptime);
}
}
catch (Exception e){
if (lives()){
System.out.println("++++++++++++++++++ Basic Process - Producer");
kill();
nf.notify(false, processnumber);
}
return;
}
}
}
}
class Consumer extends Thread{
public void run() {
while (alive) {
byte[] message = null;
Messagetimestamped mt;
synchronized(list) {
while (list.size() == 0) {
try {
list.wait(); //HANGS HERE!
if (!alive) return;
sleep(1);
}
catch (InterruptedException ex) {}
}
mt = list.removeLast();
list.notifyAll();
}
message = mt.mensaje;
try{
long timewaited = System.currentTimeMillis()-mt.timestamp;
if (timewaited < SLEEPTIME)
sleep (SLEEPTIME-timewaited);
if ( s.isClosed() || s.isOutputShutdown() ){
System.out.println("++++++++++++++++++++ Basic Process - Consumer - Connection closed!(HLR)");
kill();
nf.notify(false, processnumber);
}
else {
br.write(message);
br.flush();
}
} catch(SocketException e){
return;
} catch (Exception e){
e.printStackTrace();
}
}
}
}
Basically after alive is set to false Producer gets actually terminated.
Consumer doesn't. It just stays hanging on the list.wait() line.
Obviously the list.notify() (or list.notifyAll()?) from Producer isn't delivered after it's terminated so Consumer never gets to check the alive boolean.
How to solve this using as little modifications as possible?
Thanks.
I would just use an ExecutorService which will wrap up the queue, manage your thread(s) and handle shutdown for you. Almost all your code will go away if you do.
But to answer your question, I suggest sending a poison pill. A special object which the consumer will shutdown when it receives it.
I wrote a thread class that checks the socket connection to the server by sending a small string every one second.
begin() method executes the thread.
After connection is lost, the thread tries to connect again.
My question is if it's ok to re-run by begin() the thread inside the run() method like I did (see below).
public void begin() {
Check = new Thread(this);
Check.start();
}
#Override
public void run() {
Thread thisThread = Thread.currentThread();
while (Check==thisThread) {
try {
oos.writeObject("a");
// oos.flush();
synchronized (this) {
while (pleaseWait) {
try {
System.out.println("waiting");
wait();
System.out.println("not waiting");
}
catch (Exception e) {
System.err.println("Thread is interrupted: "+e.getMessage());
}
}
}
sleep(1000);
} catch (Exception ex) {
v = new Visual("The connection is lost. The system will try to reconnect now.");
this.end();
try {
Server=ClientLogin.checkingServers(); //returns the reachable server string address
socket = new Socket(Server, ServerPort);
System.out.println("Connected: " + socket);
oos = new ObjectOutputStream(socket.getOutputStream());
begin();
v = new Visual("The system is reconnected.");
}
catch(UnknownHostException uhe){
System.out.println("Host unknown: " + uhe.getMessage());
v = new Visual("The system has failed to reconnected.");
}
catch (IOException ioe) {
System.out.println("The system cannot connect to servers: " + ioe.getMessage());
v = new Visual("The system has failed to reconnected.");
}
catch (Exception e) {
System.out.println("The system has failed to reconnect: " + e.getMessage());
v = new Visual("The system has failed to reconnected.");
}
}
}
}
public void end() {
Check = null;
}
I don't know any reason why that wouldn't work, but it looks kinda messy. You may have to declare Check as volatile to ensure that the loop always reads the current value, for those times when the new thread overwrites it.
IMHO a better approach would be a separate "supervisor" thread which is responsible for starting one of these threads, and then uses Thread.join() to wait for it to die, at which point it can start it up again.
In this way your main thread's logic can concentrate on exactly what it's supposed to do, without needing to have any "self awareness".
First, the code is not thread safe. The "Check" field is written by one thread but read by another, but it is not synchronised. There is no guarantee that the new started thread is going to see the updated value of "Check", i.e. the new thread will get the old thread's reference when checking "Check==thisThread" and do the wrong thing,
This particular problem can be fixed by making "Check" field volatile. It makes sure when it is updated, every thread will see the new value.
It is not "wrong" to call "begin()" in the run() method. However I wouldn't recommend it because you created a recursive call here effectively. There is a good chance you will get it wrong and fall into infinite loop. Try the simple design below. It uses a while loop instead of recursion.
package com.thinkinginobjects;
public class HeathChecker {
public void run() {
while (true) {
boolean success = checkHeath();
if (!success) {
//log and re-establish connection
} else {
Thread.sleep(1000);
}
}
}
private boolean checkHeath() {
try {
oos.writeObject("a");
return true;
} catch (Exception ex) {
return false;
}
}
}
it is ok, however why do you need to start a thread every time? Isn't it better to use Timer and TimerTask?
http://docs.oracle.com/javase/6/docs/api/java/util/TimerTask.html
http://docs.oracle.com/javase/6/docs/api/java/util/Timer.html