Java thread work unexpected - java

I am reading this topic about java Thread.
And there is an example:
import java.util.Vector;
class Producer extends Thread {
static final int MAXQUEUE = 5;
private Vector messages = new Vector();
#Override
public void run() {
try {
while (true) {
putMessage();
//sleep(5000);
}
} catch (InterruptedException e) {
}
}
private synchronized void putMessage() throws InterruptedException {
while (messages.size() == MAXQUEUE) {
wait();
}
messages.addElement(new java.util.Date().toString());
System.out.println("put message");
notify();
//Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object.
}
// Called by Consumer
public synchronized String getMessage() throws InterruptedException {
notify();
while (messages.size() == 0) {
wait();//By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep.
}
String message = (String) messages.firstElement();
messages.removeElement(message);
return message;
}
}
class Consumer extends Thread {
Producer producer;
Consumer(Producer p) {
producer = p;
}
#Override
public void run() {
try {
while (true) {
String message = producer.getMessage();
System.out.println("Got message: " + message);
//sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
Producer producer = new Producer();
producer.start();
new Consumer(producer).start();
}
}
And the author said:
A possible output sequence:
Got message: Fri Dec 02 21:37:21 EST 2011
put message
put message
put message
put message
put message
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
put message
put message
put message
put message
put message
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
But when I run this code I got this result:
put message
put message
put message
put message
put message
put message
Got message: Tue Sep 24 16:44:59 CST 2013
Got message: Tue Sep 24 16:45:00 CST 2013
put message
Got message: Tue Sep 24 16:45:00 CST 2013
put message
Got message: Tue Sep 24 16:45:00 CST 2013
put message
..............
What is the problem?
Any one can explain it for me?

The author's entire point is that the order of tasks between different threads is unpredictable. He printed a possible output sequence, but many, many others are possible.

In addition to the already explained output I must add that the book you are reading doesn't seem to be a very good source to learn from. It teaches to:
extend Thread, a notorious bad practice;
invoke wait and notify on a Thread instance—another known, documented bad practice.
use the wait and notify mechanism in the first place, which has mostly been superseded by much more convenient and simpler java.util.concurrent tools such as CountDownLatch, Semaphore, and Phaser.

Your version of output is correct. Because "Got Message" is not possible without "put message". I mean, if there is no message in queue then how can you retrieve the message. Developer in his example might have given sample output which was not actual code run output but self made just for example.
Remember :
[Count of total "Got message" till particular line] will always be <= [Count of total "put message" till that very line]

The only strange thing is that there are 6 consecutive "put message" which seems to be impossible because the maximum queue size is 5.
But this is because the code sequence
producer.getMessage()
System.out.println("Got message: " + message);
is - of course - not atomic and has been interrupted by a thread switch.
By the way - always use notifyAll() instead of notify.

Related

Displaying messages on regular intervals on browser

This is what I have in my Servlet.
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("Initializing...");
ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.execute(new Runnable() {
public void run() {
System.out.println("Inside Thread!!!");
for(int i=1; i<5; i++){
System.out.println("Date: " + new Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
executorService.shutdown();
// Some more piece of code is there
}
What I am doing here:
I have created a separate thread where the date gets printed after 5 sec in the console.
What I want to do:
When I run this code, I get this output printed in the console:
Initializing...
Inside Thread!!!
Date : Sat Nov 01 15:57:57 GMT 2014
Date : Sat Nov 01 15:58:02 GMT 2014
Date : Sat Nov 01 15:58:07 GMT 2014
Date : Sat Nov 01 15:58:12 GMT 2014
I want the same set of messages to be printed in a jsp page in such a way that the Date gets printed in an interval of 5 sec (by sending multiple response to the browser whenever a Syetem.out.println() method is executed int he above code).
Reason for pushing message from server:
In the above example, I am printing simple messages in a loop. But in real scenario, there are some calculations, hence the messages will be available at different time frames (i.e. not after every 5 sec, some messages will be available in quick time while the other messages might take some more time). Hence if I push from the server, then I can push the messages whenever it is available.
Unable to understand:
I am not sure how to send multiple response to the browser from a separate thread (i.e. from ExecutorService in the above code). I was looking into the setInterval method present in javascript but am not sue how to frame this code using it.
I am free to use jQuery or javascript to get this work. Please advise.
Instead of trying to push from the server, you should have the client make an AJAX request every five seconds, and you should return the snippet that you want printed from that endpoint.

ScheduledExecutorService wait for task to complete

I am creating a new thread to check a folder for new files then sleeping for a defined period of time.
My preference would be to use the ScheduledExecutorService, however, I can't find any documentation to clarify if this waits for the currently running task to complete before starting a new one.
For example, in the following code;
Integer samplingInterval = 30;
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(10);
executorService.scheduleAtFixedRate(new WatchAgent(agentInfo),
0,
samplingInterval,
TimeUnit.SECONDS);
If the run() of WatchAgent takes longer than 30 seconds, will a new agent be created before it finishes?
Secondly, if I create an instance of WatchAgent, can I keep using the same instance for each periodic run?
Per the javadoc of scheduleAtFixedRate:
If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
scheduleAtFixedRate by definition takes a single Runnable instance. There is no way for you to provide different instances for each invocation of run. So to answer your question, the same instance will always be used for each periodic run.
Try this test code below.
1) Yes, it seems to wait until run() is finished.
2) Yes, seems it is using the same instance's run method (the one you passed in when you called scheduleAtFixedRate; this makes perfect sense btw).
import java.util.Date;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Test006 {
public static void main(String[] args) {
Object agentInfo = null;
Integer samplingInterval = 30;
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(10);
executorService.scheduleAtFixedRate(new WatchAgent(agentInfo), 0, samplingInterval, TimeUnit.SECONDS);
}
}
class WatchAgent implements Runnable {
public WatchAgent(Object info){
}
public void run(){
try{
System.out.println("Running " + this.hashCode() + " - started on/at " + (new Date()));
Thread.sleep(60000);
System.out.println("Running " + this.hashCode() + " - finished on/at " + (new Date()));
}catch(Exception ex){
ex.printStackTrace();
}
}
}
Output:
Running 1322575120 - started on/at Mon Jul 08 19:58:41 IST 2019
Running 1322575120 - finished on/at Mon Jul 08 19:59:41 IST 2019
Running 1322575120 - started on/at Mon Jul 08 19:59:41 IST 2019
Running 1322575120 - finished on/at Mon Jul 08 20:00:41 IST 2019
Running 1322575120 - started on/at Mon Jul 08 20:00:41 IST 2019
...

Search new twitter with a specific hashtag form a stream with twitter4j

I need my java app to be updated on all the new tweet with a specific hashtag (let's say #test) with twitter4j. Due to avoiding continuous polling on twitter REST API I'll gonna use Twitter Stream API.
Running this code I'm expecting to:
Run the code
Open a browser, go to twitter and post the a tweet that contains #test
See the print on my app only for tweet with a certain hashcode
But.. I do not see anything in my app.. (SEE THE EDIT)
Someone can give me some advice?
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
.setOAuthConsumerKey(CONSUMER_KEY)
.setOAuthConsumerSecret(CONSUMER_SECRET)
.setOAuthAccessToken(ACCESS_TOKEN)
.setOAuthAccessTokenSecret(ACCESS_TOKEN_SECRET);
TwitterStream twitterStream = new TwitterStreamFactory(cb.build()).getInstance();
StatusListener listener = new StatusListener() {
#Override
public void onStatus(Status status) {
System.out.println("#" + status.getUser().getScreenName() + " - " + status.getUser().getId() + " - " + status.getText());
}
#Override
public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
System.out.println("Post Deletado:" + statusDeletionNotice.getStatusId());
}
#Override
public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
System.err.println("Limitação:" + numberOfLimitedStatuses);
}
#Override
public void onScrubGeo(long userId, long upToStatusId) {
System.out.println("Got scrub_geo event userId:" + userId + " upToStatusId:" + upToStatusId);
}
#Override
public void onStallWarning(StallWarning warning) {
System.out.println("Got stall warning:" + warning);
}
#Override
public void onException(Exception ex) {
ex.printStackTrace();
}
};
List<String> queries = new ArrayList<String>();
queries.add("#test");
twitterStream.addListener(listener);
twitterStream.firehose(20);
String[] trackQueries = (String[]) queries.toArray(new String[queries.size()]);
FilterQuery filterQuery = new FilterQuery();
twitterStream.filter(filterQuery.track(trackQueries));
EDIT:
After some errors fixed I'm reading something in the sys.out but.. it seems random stuffs after some errors:
[Tue Jul 02 14:58:30 CEST 2013]Establishing connection.
[Tue Jul 02 14:58:30 CEST 2013]Establishing connection.
[Tue Jul 02 14:58:31 CEST 2013]Connection established.
[Tue Jul 02 14:58:31 CEST 2013]Receiving status stream.
[Tue Jul 02 14:58:31 CEST 2013]Connection established.
[Tue Jul 02 14:58:31 CEST 2013]Receiving status stream.
[Tue Jul 02 14:58:31 CEST 2013]Stream closed.
[Tue Jul 02 14:58:31 CEST 2013]Stream closed.
[Tue Jul 02 14:58:31 CEST 2013]Waiting for 250 milliseconds
Stream closed.
Relevant discussions can be found on the Internet at:
http://www.google.co.jp/search?q=a8fd061d or
http://www.google.co.jp/search?q=00070a0c
TwitterException{exceptionCode=[a8fd061d-00070a0c a8fd061d-0007099d], statusCode=-1, message=null, code=-1, retryAfter=-1, rateLimitStatus=null, version=3.0.3}
at twitter4j.StatusStreamBase.handleNextElement(StatusStreamBase.java:199)
at twitter4j.StatusStreamImpl.next(StatusStreamImpl.java:57)
at twitter4j.TwitterStreamImpl$TwitterStreamConsumer.run(TwitterStreamImpl.java:478)
Caused by: java.io.IOException: the end of the stream has been reached
at twitter4j.StatusStreamBase.handleNextElement(StatusStreamBase.java:88)
... 2 more
Stream closed.
Relevant discussions can be found on the Internet at:
http://www.google.co.jp/search?q=a8fd061d or
http://www.google.co.jp/search?q=00070a0c
TwitterException{exceptionCode=[a8fd061d-00070a0c a8fd061d-0007099d], statusCode=-1, message=null, code=-1, retryAfter=-1, rateLimitStatus=null, version=3.0.3}
at twitter4j.StatusStreamBase.handleNextElement(StatusStreamBase.java:199)
at twitter4j.StatusStreamImpl.next(StatusStreamImpl.java:57)
at twitter4j.TwitterStreamImpl$TwitterStreamConsumer.run(TwitterStreamImpl.java:478)
Caused by: java.io.IOException: the end of the stream has been reached
at twitter4j.StatusStreamBase.handleNextElement(StatusStreamBase.java:88)
... 2 more
[Tue Jul 02 14:58:31 CEST 2013]Unhandled event: {"disconnect":{"code":7,"stream_name":"urbanspirit5-statuses1734930","reason":"admin logout"}}
[Tue Jul 02 14:58:32 CEST 2013]Establishing connection.
[Tue Jul 02 14:58:33 CEST 2013]Connection established.
[Tue Jul 02 14:58:33 CEST 2013]Receiving status stream.
And then some random tweets like this:
#markinhos_jm - 300044892 - CRAZY PARTY AGUARDEM!!!
#bindibba7 - 511548205 - ??????? .. ??????? = ?? ??? ????
#Tamirmdty - 1521605059 - Salah ngetik
#PAOLOves_you - 222755754 - Hirap ah. Text, Chat FB at Tweet? SIYET! #MedyoAZARitu
#agokichi_mmmm - 793252368 - ???DVD??????
Access to twitter firehose is only given to selected companies via resellers. So unless you are one of those companies, you want to use sample() instead of firehose. You should see some logs though. Are you sure your loggers are set up correctly?
EDIT: Read this section of the documentation and add a valid twitter4j.properties file. Note that you have to sign up with twitter to get an access token. Once you have a token and filled the config file, you can just include it in your classpath.

Pig error 1070 when doing UDF

I am trying to load up my own UDF in pig. I have made it into a jar using eclipse's export function. I am trying to run it locally so I can make sure it works before I put the jar on HDFS. When running it locally, I get the following error:
ERROR 1070: Could not resolve myudfs.MONTH using imports: [, org.apache.pig.builtin., org.apache.pig.impl.builtin.]
Script
REGISTER myudfs.jar;
--DEFINE MONTH myudfs.MONTH;
A = load 'access_log_Jul95' using PigStorage(' ') as (ip:chararray, dash1:chararray, dash2:chararray, date:chararray, getRequset:chararray, status:int, port:int);
B = FOREACH A GENERATE myudfs.MONTH(date);
DUMP B;
Function
package myudfs;
import java.io.IOException;
import org.apache.pig.EvalFunc;
import org.apache.pig.data.Tuple;
import org.apache.pig.impl.util.WrappedIOException;
#SuppressWarnings("deprecation")
public class HOUR extends EvalFunc<String>
{
public String exec(Tuple input) throws IOException {
if (input == null || input.size() == 0)
return null;
try{
String str = (String)input.get(0);
return str.substring(1, 3);
}catch(Exception e){
throw WrappedIOException.wrap("Caught exception processing input row ", e);
}
}
}
Working Directory
1.pig 2.pig bin myudfs.jar
pig.jar pig-withouthadoop.jar src/
Running command
pig -x local 2.pig
Structure of jar
0 Thu May 02 12:16:26 MDT 2013 META-INF/
68 Thu May 02 12:16:26 MDT 2013 META-INF/MANIFEST.MF
0 Thu May 02 12:05:50 MDT 2013 myudfs/
573 Thu May 02 12:15:10 MDT 2013 myudfs/HOUR.java
I am really close to start chucking monitors, so I am just looking for some help and direction. Let me know what could be wrong.
Your UDF class name is called HOUR
So shouldn't your pig latin be this?
B = FOREACH A GENERATE myudfs.HOUR(date);

mail reading problem?

i have com.sun.mail.pop3.POP3Message object, in that content i have the following format code,
Delivery has failed to these recipients or distribution lists:
anandnarekar#gmail.coxm
An error occurred while trying to deliver this message to the recipient's e-mail address. Microsoft Exchange will not try to redeliver this message for you. Please try resending this message, or provide the following diagnostic text to your system administrator.
Diagnostic information for administrators:
Generating server: delivery
anandnarekar#gmail.coxm
#< #5.0.0 smtp; 554 5.4.4 [internal] Domain Lookup Failed> #SMTP#
Original message headers:
X-AuditID: ac1ec426-b7b3aae0000036b3-7c-4e3009fd2d34
Received: from SVHJ0032 ( [172.30.1.11]) by svhj0367.ideaconnect.com (Symantec
Brightmail Gateway) with SMTP id BA.D0.14003.DF9003E4; Wed, 27 Jul 2011
18:22:13 +0530 (IST)
Message-ID: <1502435725.1311770110726.JavaMail.wasadmin#SVHJ0032>
Date: Wed, 27 Jul 2011 18:05:10 +0530
From: <ebill.mh#idea.adityabirla.com>
To: <anandnarekar#gmail.coxm>
Subject: Your Idea Bill
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_Part_67575_1171670486.1311770110725"
Thread-Topic: rsweb_7202772011060510
X-Brightmail-Tracker: AAAAAQAAAZE= </pre>
> Blockquote
how can I retrieve the value of Thread-Topic?
Loop through the text that gets returned to you and look for "Thread-Topic".
Once you find it, you can use the indexOf and substring functions to parse out your topic.
Sample code shown below:
E:\jdk1.6.0_23\bin>type Test.java
public class Test
{
public static void main(String[] args) {
String str = "Thread-Topic: rsweb_7202772011060510";
if (str.indexOf("Thread-Topic") != -1) {
String topic = str.substring(str.indexOf(":") + 2);
System.out.println(topic);
}
}
}
E:\jdk1.6.0_23\bin>javac Test.java
E:\jdk1.6.0_23\bin>java Test
rsweb_7202772011060510

Categories