Java, GTFS Realtime, protocol buffers, simple get? - java

Im using this thing:
https://github.com/MobilityData/gtfs-realtime-bindings/tree/final-google-version/java
And I can follow the code-example given. But it only takes me thus far, I dont get how to extract the more fine-grained information. I would like to know how to simply extract the delay for a certain trip, or a stop_id. Can anyone help me?

The following java program:
package com.google.transit.realtime;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.Date;
import com.google.transit.realtime.GtfsRealtime.FeedEntity;
import com.google.transit.realtime.GtfsRealtime.FeedHeader;
import com.google.transit.realtime.GtfsRealtime.FeedMessage;
import com.google.transit.realtime.GtfsRealtime.TripDescriptor;
import com.google.transit.realtime.GtfsRealtime.TripUpdate;
import com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate;
public class GtfsRealtimeExample {
public static void main(String[] args) throws Exception {
URL url;
String outputFile;
if (args[0].startsWith("http")) {
url = new URL(args[0]);
outputFile = args[0].substring(args[0].lastIndexOf('/')+1).replaceFirst(".pb", ".txt");
}
else {
url = new File(args[0]).toURI().toURL();
outputFile = args[0].replaceFirst(".pb", ".txt");
}
FeedMessage feed = FeedMessage.parseFrom(url.openStream());
FeedHeader header = feed.getHeader();
OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(outputFile));
os.write(String.format("GTFS Realtime Version %s feed produced on %s with %d entities\n",
header.getGtfsRealtimeVersion(), new Date(header.getTimestamp()*1000).toString(), feed.getEntityCount()));
for (FeedEntity entity : feed.getEntityList()) {
if (entity.hasTripUpdate()) {
TripUpdate tripUpdate = entity.getTripUpdate();
int noStopTimeUpdates = tripUpdate.getStopTimeUpdateCount();
int tripDelay = tripUpdate.getDelay();
long tripTimestamp = tripUpdate.getTimestamp();
TripDescriptor tripDescriptor = tripUpdate.getTrip();
os.write(String.format("\nTRIP id=%s route=%s direction=%d, sch=%s, date=%s, time=%s, noStopUpdates=%d tripDelay=%d timestamp=%d\n",
tripDescriptor.getTripId(), tripDescriptor.getRouteId(), tripDescriptor.getDirectionId(),
tripDescriptor.getScheduleRelationship().getValueDescriptor().toString(), tripDescriptor.getStartDate(),
tripDescriptor.getStartTime(), noStopTimeUpdates, tripDelay, tripTimestamp));
for (StopTimeUpdate stoptimeUpdate : tripUpdate.getStopTimeUpdateList()) {
os.write(String.format(" STOP id=%s seq=%d sch=%s arrTime=%s arrDelay=%d depTime=%s depDelay=%d\n",
stoptimeUpdate.getStopId(), stoptimeUpdate.getStopSequence(),
stoptimeUpdate.getScheduleRelationship().getValueDescriptor().toString(),
new Date(stoptimeUpdate.getArrival().getTime()*1000).toString(), stoptimeUpdate.getArrival().getDelay(),
new Date(stoptimeUpdate.getDeparture().getTime()*1000).toString(), stoptimeUpdate.getDeparture().getDelay()));
}
}
}
os.close();
}
}
when run with an argument http://api.nextlift.ca/gtfs-realtime/tripupdates.pb will produce an output file tripupdates.txt which contains:
GTFS Realtime Version 1.0 feed produced on Wed Jun 12 15:50:33 IST 2019 with 118 entities
TRIP id=10559:203976 route=1 direction=0, sch=SCHEDULED, date=20190612, time=, noStopUpdates=54 tripDelay=0 timestamp=0 STOP id=1150 seq=1 sch=SCHEDULED arrTime=Thu Jan 01 01:00:00 GMT 1970 arrDelay=0 depTime=Wed Jun 12 16:07:00 IST 2019 depDelay=0
STOP id=1152 seq=2 sch=SCHEDULED arrTime=Wed Jun 12 16:07:00 IST 2019 arrDelay=0 depTime=Wed Jun 12 16:07:00 IST 2019 depDelay=0
STOP id=1153 seq=3 sch=SCHEDULED arrTime=Wed Jun 12 16:08:00 IST 2019 arrDelay=0 depTime=Wed Jun 12 16:08:00 IST 2019 depDelay=0
...
...
STOP id=1005 seq=53 sch=SCHEDULED arrTime=Wed Jun 12 16:44:00 IST 2019 arrDelay=0 depTime=Wed Jun 12 16:44:00 IST 2019 depDelay=0 STOP id=1006 seq=54 sch=SCHEDULED arrTime=Wed Jun 12 16:47:00 IST 2019 arrDelay=0 depTime=Wed Jun 12 16:47:00 IST 2019 depDelay=0
TRIP id=10558:203580 route=1 direction=0, sch=SCHEDULED, date=20190612, time=, noStopUpdates=69 tripDelay=0 timestamp=0
STOP id=1177 seq=24 sch=SCHEDULED arrTime=Wed Jun 12 15:50:16 IST 2019 arrDelay=0 depTime=Wed Jun 12 15:50:16 IST 2019 depDelay=0 STOP id=1178 seq=25 sch=SCHEDULED arrTime=Wed Jun 12 15:50:35 IST 2019 arrDelay=0 depTime=Wed Jun 12 15:50:35 IST 2019 depDelay=0
STOP id=1179 seq=26 sch=SCHEDULED arrTime=Wed Jun 12 15:51:14 IST 2019 arrDelay=0 depTime=Wed Jun 12 15:51:22 IST 2019 depDelay=0 STOP id=1180 seq=27 sch=SCHEDULED arrTime=Wed Jun 12 15:52:21 IST 2019 arrDelay=0 depTime=Wed Jun 12 15:52:43 IST 2019 depDelay=0
...
...
...
...

Related

java.util.GregorianCalendar issue with add() when applying DST changes

My requirement is determining the next date based on frequency of schedule.
So if frequency is DAILY and the first date is 25-Oct-2015 23:59:59,
the next duedate should be exactly 24 hours apart ie 26-Oct-2015 23:59:59
Calendar.add(int field, int amount) seems to be taking care of the same
Eg:
DAILY frequency -- calendar.add(Calendar.DATE, 1);
WEEKLY frequency -- calendar.add(Calendar.DATE, 7);
MONTHLY frequency -- calendar.add(Calendar.MONTH, 1);
The following is the code abstract of the same:
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar();
for(int i=0;i<10;i++) {
calendar.add(Calendar.DATE, 1);
System.out.println(calendar.getTime());
}
}
==================================================
Thu Oct 29 17:17:26 IST 2015 -- in all cases diff is 24 hrs
Fri Oct 30 17:17:26 IST 2015
Sat Oct 31 17:17:26 IST 2015
Sun Nov 01 17:17:26 IST 2015
Mon Nov 02 17:17:26 IST 2015
Tue Nov 03 17:17:26 IST 2015
Wed Nov 04 17:17:26 IST 2015
Thu Nov 05 17:17:26 IST 2015
Fri Nov 06 17:17:26 IST 2015
In case of DAILY frequency and server being in Eastern time (EDT), a few anomaly was ocuuring with add()
As of Nov-1, DST settings change the same are reflected in add
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getTimeZone("US/Eastern"));
for(int i=0;i<10;i++) {
calendar.add(Calendar.DATE, 1);
System.out.println(calendar.getTime());
}
}
-------------------------------------
Wed Oct 28 17:18:14 IST 2015
Thu Oct 29 17:18:14 IST 2015
Fri Oct 30 17:18:14 IST 2015
Sat Oct 31 17:18:14 IST 2015
Sun Nov 01 18:18:14 IST 2015 -- here diff is of 24 + 1 hr
Mon Nov 02 18:18:14 IST 2015
Tue Nov 03 18:18:14 IST 2015
Wed Nov 04 18:18:14 IST 2015 -- else everywhere diff is 24 hours
Thu Nov 05 18:18:14 IST 2015
Fri Nov 06 18:18:14 IST 2015
In case by first date is 25-Oct-2015 23:59:59, in this case, the extra 1 hour shift is causing anomaly as after
31-Oct-2015 23:59:59,
the next date is 2-Nov-2015 00:59:59
Further observing the Code, found out that
// The rest of the fields (week, day or AM_PM fields)
// require time zone offset (both GMT and DST) change
// adjustment.
Actually the server is in EDT, where I'm getting following I/O relation.
I merely tried to debug it on my local instance which is in IST.
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar();
for(int i=0;i<10;i++) {
calendar.add(Calendar.DATE, 1);
System.out.println(calendar.getTime());
}
}
Wed Oct 28 08:09:48 EDT 2015
Thu Oct 29 08:09:48 EDT 2015
Fri Oct 30 08:09:48 EDT 2015
Sat Oct 31 08:09:48 EDT 2015
Sun Nov 01 08:09:48 EST 2015
Mon Nov 02 08:09:48 EST 2015
Tue Nov 03 08:09:48 EST 2015
Wed Nov 04 08:09:48 EST 2015
Thu Nov 05 08:09:48 EST 2015
Fri Nov 06 08:09:48 EST 2015
What should be a reliable way of using a library to ensure that my dates generated are in proper sequence.
Try the below code. The below code doesn't simpley add 1 to DAY or MONTH. It adds milliseconds for a day in order to get the proper result.
public static void main(String[] args) {
DateFormat formatter = new SimpleDateFormat("EEE MMM dd hh:mm:ss z yyyy");
Calendar calendar = Calendar.getInstance();
formatter.setTimeZone(TimeZone.getTimeZone("US/Eastern"));
calendar.setTimeInMillis(System.currentTimeMillis());
long time = calendar.getTimeInMillis();
for(int i=0;i<10;i++) {
System.out.println(formatter.format(calendar.getTime()));
time = time + 86400000;
calendar.setTimeInMillis(time);
}
}
Definitely formatting of the date can be changed by changing the line -
new SimpleDateFormat("E MMM dd hh:mm:ss z yyyy");
It gives output -
Di Okt 27 08:15:59 EDT 2015
Mi Okt 28 08:15:59 EDT 2015
Do Okt 29 08:15:59 EDT 2015
Fr Okt 30 08:15:59 EDT 2015
Sa Okt 31 08:15:59 EDT 2015
So Nov 01 07:15:59 EST 2015
Mo Nov 02 07:15:59 EST 2015
Di Nov 03 07:15:59 EST 2015
Mi Nov 04 07:15:59 EST 2015
Do Nov 05 07:15:59 EST 2015
I think the anomaly is because, the daylight is ending for EDT zone on that day(31st October night).
NO such problem is occurring for IST as India do not have daylight saving.

How do I get my "Date" object to print out different values each time I call it?

I have been asked to add println statements throughout an existing project so that the dates/times of each process can be printed out as they execute.
The first thing I should mention is that I have to stick to Java 7 due to project constraints. I am aware that Java 8 has a nice little LocalDateTime.now() function to make determining the current date and time a hell of a lot easier, shame we can't use it.
Anyway. I've written a mini project to test this functionality before I build it into the existing code.
I have a class CreateDate that allows me to create a new Date object and print out the current date/time as follows:
package datetest;
import java.util.Date;
public class CreateDate {
public void returnDate() {
Date date = new Date();
System.out.println("The current date and time is: " + date);
}
}
I have another class, Printer, that creates an instance of CreateDate and calls the returnDate method as follows:
package datetest;
public class Printer {
public static void main(String[] args) {
CreateDate date = new CreateDate();
date.returnDate();
}
}
However, no matter how many times I try to print out the current date/time, the date object is initialised with the same date and time, every time. I'm looking to print out different dates to specify the current time that something is being executed.
Please help! I'm relatively new to Java, so any advice you could offer would be much appreciated.
You have to "save" the object in some field - you are creating new Date object every time you call returnDate method, so:
public class CreateDate {
protected Date date;
public CreateDate() {
this.date = new Date();
}
public void returnDate() {
System.out.println("The current date and time is: " + this.date);
}
}
I think you're over complicating this. The following program prints a different date each time it is run:
import java.util.Date;
public class Main {
public static void main(String[] args) {
System.out.println("The current time is "+new Date());
}
}
If you want it factored out, then:
import java.util.Date;
public class Printer {
static public void printCurrentTime() {
System.out.println("The current time is " + new Date());
}
}
With:
public class Main {
public static void main(String[] args) throws Exception {
for( int i = 0; i< 10; i++) {
Printer.printCurrentTime();
Thread.sleep(10000);
}
}
}
This program produces
The current time is Wed Oct 14 11:10:40 BST 2015
The current time is Wed Oct 14 11:10:50 BST 2015
The current time is Wed Oct 14 11:11:00 BST 2015
The current time is Wed Oct 14 11:11:10 BST 2015
The current time is Wed Oct 14 11:11:20 BST 2015
The current time is Wed Oct 14 11:11:30 BST 2015
The current time is Wed Oct 14 11:11:40 BST 2015
The current time is Wed Oct 14 11:11:50 BST 2015
The current time is Wed Oct 14 11:12:00 BST 2015
The current time is Wed Oct 14 11:12:10 BST 2015
import java.util.Date;
public class MyDate {
private Date date;
#Override
public String toString() {
date = new Date();
return date.toString();
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public static void main(String[] args) throws InterruptedException {
MyDate currentDate = new MyDate();
for(int i = 0; i < 100; i++) {
Thread.sleep(100);
System.out.println(currentDate);
}
}
}
produces
Wed Oct 14 16:14:19 IST 2015
Wed Oct 14 16:14:20 IST 2015
Wed Oct 14 16:14:20 IST 2015
Wed Oct 14 16:14:20 IST 2015
Wed Oct 14 16:14:20 IST 2015
Wed Oct 14 16:14:20 IST 2015
Wed Oct 14 16:14:20 IST 2015
Wed Oct 14 16:14:20 IST 2015
Wed Oct 14 16:14:20 IST 2015
Wed Oct 14 16:14:20 IST 2015
Wed Oct 14 16:14:20 IST 2015
Wed Oct 14 16:14:21 IST 2015
Wed Oct 14 16:14:21 IST 2015
Wed Oct 14 16:14:21 IST 2015
Wed Oct 14 16:14:21 IST 2015
Wed Oct 14 16:14:21 IST 2015
Wed Oct 14 16:14:21 IST 2015
Wed Oct 14 16:14:21 IST 2015
Wed Oct 14 16:14:21 IST 2015
Wed Oct 14 16:14:21 IST 2015

json to HashMap<Date, Integer>

I have to convert json Strings like this
{"Tue Jan 13 00:00:00 MEZ 2015":2131165194,"Mon Jan 12 00:00:00 MEZ 2015":2131165194,
"Thu Dec 11 00:00:00 MEZ 2014":2131165194,"Fri Dec 12 00:00:00 MEZ 2014":2131165194,
"Mon Jan 19 00:00:00 MEZ 2015":2131165194,"Wed Dec 10 00:00:00 MEZ 2014":2131165194,
"Mon Jan 05 00:00:00 MEZ 2015":2131165194}
into a HashMap.
Is it really necessary to write a parser?
I try to avoid this, because I never made this bevor, and it seems quite difficult. I would be glad for any help and thanks in advance!
If your keys are unique – you can use the next code
String s = "{\"Tue Jan 13 00:00:00 MEZ 2015\":2131165194,\"Mon Jan 12 00:00:00 MEZ 2015\":2131165194,\n" +
"\"Thu Dec 11 00:00:00 MEZ 2014\":2131165194,\"Fri Dec 12 00:00:00 MEZ 2014\":2131165194,\n" +
"\"Mon Jan 19 00:00:00 MEZ 2015\":2131165194,\"Wed Dec 10 00:00:00 MEZ 2014\":2131165194,\n" +
"\"Mon Jan 05 00:00:00 MEZ 2015\":2131165194}";
Map<Date, Long> map = new GsonBuilder().setDateFormat("E MMM dd HH:mm:ss 'MEZ' yyyy").create().fromJson(s, new TypeToken<HashMap<Date, Long>>() {
}.getType());
Since you mentioned about Gson , you need to set the date format for the Gson object(you can build it via GsonBuilder) and then declare TypeToken<Map<Date, Integer>> after that just invoke fromJson E.g.
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.Map;
public class Test {
public static void main(String[] args) {
String json = "{\"Tue Jan 13 00:00:00 MEZ 2015\":2131165194,\"Mon Jan 12 00:00:00 MEZ 2015\":2131165194,\n" +
"\"Thu Dec 11 00:00:00 MEZ 2014\":2131165194,\"Fri Dec 12 00:00:00 MEZ 2014\":2131165194,\n" +
"\"Mon Jan 19 00:00:00 MEZ 2015\":2131165194,\"Wed Dec 10 00:00:00 MEZ 2014\":2131165194,\n" +
"\"Mon Jan 05 00:00:00 MEZ 2015\":2131165194}";
Type type = new TypeToken<Map<Date, Integer>>() {
}.getType();
Gson gson = new GsonBuilder().setDateFormat("EEE MMM dd HH:mm:ss 'MEZ' yyyy").create();
Map<String, String> myMap = gson.fromJson(json, type);
System.out.println(myMap);
}
}
Output
{Tue Jan 13 00:00:00 CET 2015=2131165194, Mon Jan 12 00:00:00 CET 2015=2131165194, Thu Dec 11 00:00:00 CET 2014=2131165194, Fri Dec 12 00:00:00 CET 2014=2131165194, Mon Jan 19 00:00:00 CET 2015=2131165194, Wed Dec 10 00:00:00 CET 2014=2131165194, Mon Jan 05 00:00:00 CET 2015=2131165194}

Java - Define a timeout for Callable within a ExecutorCompletionService

I've got the following problem using ExecutorCompletionService. I want to call a lot of Callable in different Threads. These Callable don't share any information with each other. I need to define a timeout for each Callable, eg. do not run longer than 5 seconds. Each Callable can run in a different time that I do not know when starting. After the timeout the Thread should be stopped/killed and the result is not interesting any more for me. The other 'normal' running Threads should not be infuenced.
So lets take the following example with a simple callable and my current java code.
import java.util.Date;
import java.util.concurrent.Callable;
public class Job implements Callable<Integer> {
int returnValue = 0;
long millis = 0;
public Job(long millis, int value) {
this.millis = millis;
this.returnValue = value;
}
#Override
public Integer call() throws Exception, InterruptedException {
try {
System.out.println(new Date() + " " + returnValue + " started");
Thread.sleep(millis);
System.out.println(new Date() + " " + returnValue + " finished");
return returnValue;
} catch (InterruptedException e) {
System.out.println(new Date() + " " + returnValue + " interrupted");
throw e;
}
}
}
And the other Class where the Callable is used.
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.*;
public class CallableTest {
public static void main(String[] args) {
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);
CompletionService<Integer> pool = new ExecutorCompletionService<Integer>(newFixedThreadPool);
for (int i = 10; i > 0; i--) {
Job job = new Job(i * 1000, i);
pool.submit(job);
}
ArrayList<Integer> results = new ArrayList<Integer>();
for (int i = 1; i < 11; ++i) {
try {
Future<Integer> future = pool.take();
Integer content = future.get(5, TimeUnit.SECONDS);
results.add(content);
System.out.println(new Date() + " added " + content);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
newFixedThreadPool.shutdownNow();
System.out.println(new Date() + " results:");
for (int j : results) {
System.out.println(new Date() + " " + j);
}
}
}
The ouput is something like:
Sun Jun 29 08:01:00 CEST 2014 10 started
Sun Jun 29 08:01:00 CEST 2014 9 started
Sun Jun 29 08:01:09 CEST 2014 9 finished
Sun Jun 29 08:01:09 CEST 2014 added 9
Sun Jun 29 08:01:09 CEST 2014 8 started
Sun Jun 29 08:01:10 CEST 2014 10 finished
Sun Jun 29 08:01:10 CEST 2014 7 started
Sun Jun 29 08:01:10 CEST 2014 added 10
Sun Jun 29 08:01:17 CEST 2014 7 finished
Sun Jun 29 08:01:17 CEST 2014 6 started
Sun Jun 29 08:01:17 CEST 2014 added 7
Sun Jun 29 08:01:17 CEST 2014 8 finished
Sun Jun 29 08:01:17 CEST 2014 added 8
Sun Jun 29 08:01:17 CEST 2014 5 started
Sun Jun 29 08:01:22 CEST 2014 5 finished
Sun Jun 29 08:01:22 CEST 2014 added 5
Sun Jun 29 08:01:22 CEST 2014 4 started
Sun Jun 29 08:01:23 CEST 2014 6 finished
Sun Jun 29 08:01:23 CEST 2014 3 started
Sun Jun 29 08:01:23 CEST 2014 added 6
Sun Jun 29 08:01:26 CEST 2014 3 finished
Sun Jun 29 08:01:26 CEST 2014 2 started
Sun Jun 29 08:01:26 CEST 2014 added 3
Sun Jun 29 08:01:26 CEST 2014 4 finished
Sun Jun 29 08:01:26 CEST 2014 1 started
Sun Jun 29 08:01:26 CEST 2014 added 4
Sun Jun 29 08:01:27 CEST 2014 1 finished
Sun Jun 29 08:01:27 CEST 2014 added 1
Sun Jun 29 08:01:28 CEST 2014 2 finished
Sun Jun 29 08:01:28 CEST 2014 added 2
Sun Jun 29 08:01:28 CEST 2014 results:
Sun Jun 29 08:01:28 CEST 2014 9
Sun Jun 29 08:01:28 CEST 2014 10
Sun Jun 29 08:01:28 CEST 2014 7
Sun Jun 29 08:01:28 CEST 2014 8
Sun Jun 29 08:01:28 CEST 2014 5
Sun Jun 29 08:01:28 CEST 2014 6
Sun Jun 29 08:01:28 CEST 2014 3
Sun Jun 29 08:01:28 CEST 2014 4
Sun Jun 29 08:01:28 CEST 2014 1
Sun Jun 29 08:01:28 CEST 2014 2
That does not work like I would like to have it. I want that each Callable running longer than 5 seconds should be terminated/ended/interruped and only the Callable running lower than 5 seconds give me a valid result.
I also tried it without the ExecutorCompletionService
public class CallableTest2 {
public static void main(String[] args) {
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);
List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
for (int i = 10; i > 0; i--) {
Job job = new Job(i * 1000, i);
futures.add(newFixedThreadPool.submit(job));
}
ArrayList<Integer> results = new ArrayList<Integer>();
for (Future<Integer> future: futures) {
try {
Integer content = future.get(5, TimeUnit.SECONDS);
results.add(content);
System.out.println(new Date() + " added " + content);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
newFixedThreadPool.shutdownNow();
System.out.println(new Date() + " results:");
for (int j : results) {
System.out.println(new Date() + " " + j);
}
}
}
With the results:
Sun Jun 29 08:33:19 CEST 2014 9 started
Sun Jun 29 08:33:19 CEST 2014 10 started
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:228)
at java.util.concurrent.FutureTask.get(FutureTask.java:91)
at callabletest.CallableTest2.main(CallableTest2.java:29)
Sun Jun 29 08:33:28 CEST 2014 9 finished
Sun Jun 29 08:33:28 CEST 2014 8 started
Sun Jun 29 08:33:28 CEST 2014 added 9
Sun Jun 29 08:33:29 CEST 2014 10 finished
Sun Jun 29 08:33:29 CEST 2014 7 started
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:228)
at java.util.concurrent.FutureTask.get(FutureTask.java:91)
at callabletest.CallableTest2.main(CallableTest2.java:29)
Sun Jun 29 08:33:36 CEST 2014 7 finished
Sun Jun 29 08:33:36 CEST 2014 added 7
Sun Jun 29 08:33:36 CEST 2014 6 started
Sun Jun 29 08:33:36 CEST 2014 8 finished
Sun Jun 29 08:33:36 CEST 2014 5 started
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask$Sync.innerGet(Sun Jun 29 08:33:41 CEST 2014 5 finished
FutureTask.java:228)
Sun Jun 29 08:33:41 CEST 2014 added 5
at java.util.concurrent.FutureTask.get(FutureTask.java:91)
Sun Jun 29 08:33:41 CEST 2014 4 started
at callabletest.CallableTest2.main(CallableTest2.java:29)
Sun Jun 29 08:33:42 CEST 2014 6 finished
Sun Jun 29 08:33:42 CEST 2014 3 started
Sun Jun 29 08:33:45 CEST 2014 3 finished
Sun Jun 29 08:33:45 CEST 2014 2 started
Sun Jun 29 08:33:45 CEST 2014 4 finished
Sun Jun 29 08:33:45 CEST 2014 added 4
Sun Jun 29 08:33:45 CEST 2014 added 3
Sun Jun 29 08:33:45 CEST 2014 1 started
Sun Jun 29 08:33:46 CEST 2014 1 finished
Sun Jun 29 08:33:47 CEST 2014 2 finished
Sun Jun 29 08:33:47 CEST 2014 added 2
Sun Jun 29 08:33:47 CEST 2014 added 1
Sun Jun 29 08:33:47 CEST 2014 results:
Sun Jun 29 08:33:47 CEST 2014 9
Sun Jun 29 08:33:47 CEST 2014 7
Sun Jun 29 08:33:47 CEST 2014 5
Sun Jun 29 08:33:47 CEST 2014 4
Sun Jun 29 08:33:47 CEST 2014 3
Sun Jun 29 08:33:47 CEST 2014 2
Sun Jun 29 08:33:47 CEST 2014 1
Now I get some TimeoutExceptions, but also not where I expect them. Eg. The Callable running 9 and 7 seconds does not throw an Exception!
What do I have to change in the code, to only get the results of the short running Threads and kill the long running ones. In the example only the results 1-5 without 6-10.
I've tested a lot of things but I can't get it to work.
Please help
This is an answer to the post of bstar55 using a ScheduledExecutorService.
I changed my code regarding to your hint to:
public class CallableTest3 {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
for (int i = 10; i > 0; i--) {
Job job = new Job(i * 1000, i);
final Future handler = executor.submit(job);
final int x = i;
executor.schedule(new Runnable() {
public void run() {
boolean cancel = handler.cancel(true);
if(cancel){
System.out.println(new Date() + " job " + x + " cancelled");
}else{
System.out.println(new Date() + " job " + x + " not cancelled");
}
}
}, 5000, TimeUnit.MILLISECONDS);
futures.add(handler);
}
ArrayList<Integer> results = new ArrayList<Integer>();
for (Future<Integer> future : futures) {
try {
Integer content = future.get(5, TimeUnit.SECONDS);
results.add(content);
System.out.println(new Date() + " added " + content);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
executor.shutdown();
System.out.println(new Date() + " results:");
for (int j : results) {
System.out.println(new Date() + " --- " + j);
}
}
}
But this also does not work as expected.
Result:
Sun Jun 29 10:27:41 CEST 2014 9 started
Sun Jun 29 10:27:41 CEST 2014 10 started
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:228)
at java.util.concurrent.FutureTask.get(FutureTask.java:91)
at callabletest.CallableTest3.main(CallableTest3.java:43)
Sun Jun 29 10:27:50 CEST 2014 9 finished
Sun Jun 29 10:27:50 CEST 2014 added 9
Sun Jun 29 10:27:50 CEST 2014 8 started
Sun Jun 29 10:27:51 CEST 2014 10 finished
Sun Jun 29 10:27:51 CEST 2014 7 started
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:228)
at java.util.concurrent.FutureTask.get(FutureTask.java:91)
at callabletest.CallableTest3.main(CallableTest3.java:43)
Sun Jun 29 10:27:58 CEST 2014 8 finished
Sun Jun 29 10:27:58 CEST 2014 6 started
Sun Jun 29 10:27:58 CEST 2014 7 finished
Sun Jun 29 10:27:58 CEST 2014 5 started
Sun Jun 29 10:27:58 CEST 2014 added 7
Sun Jun 29 10:28:03 CEST 2014 5 finished
Sun Jun 29 10:28:03 CEST 2014 4 started
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:228)
at java.util.concurrent.FutureTask.get(FutureTask.java:91)
Sun Jun 29 10:28:03 CEST 2014 added 5
at callabletest.CallableTest3.main(CallableTest3.java:43)
Sun Jun 29 10:28:04 CEST 2014 6 finished
Sun Jun 29 10:28:04 CEST 2014 3 started
Sun Jun 29 10:28:07 CEST 2014 3 finished
Sun Jun 29 10:28:07 CEST 2014 2 started
Sun Jun 29 10:28:07 CEST 2014 4 finished
Sun Jun 29 10:28:07 CEST 2014 added 4
Sun Jun 29 10:28:07 CEST 2014 added 3
Sun Jun 29 10:28:07 CEST 2014 1 started
java.util.concurrent.CancellationException
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:230)
at java.util.concurrent.FutureTask.get(FutureTask.java:91)
at callabletest.CallableTest3.main(CallableTest3.java:43)
Sun Jun 29 10:28:08 CEST 2014 1 finished
Sun Jun 29 10:28:08 CEST 2014 job 10 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 9 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 8 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 7 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 6 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 5 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 4 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 3 not cancelled
Sun Jun 29 10:28:08 CEST 2014 2 interrupted
Sun Jun 29 10:28:08 CEST 2014 job 1 not cancelled
Sun Jun 29 10:28:08 CEST 2014 added 1
Sun Jun 29 10:28:08 CEST 2014 results:
Sun Jun 29 10:28:08 CEST 2014 --- 9
Sun Jun 29 10:28:08 CEST 2014 --- 7
Sun Jun 29 10:28:08 CEST 2014 --- 5
Sun Jun 29 10:28:08 CEST 2014 --- 4
Sun Jun 29 10:28:08 CEST 2014 --- 3
Sun Jun 29 10:28:08 CEST 2014 --- 1
Sun Jun 29 10:28:08 CEST 2014 job 2 cancelled
But instead the job 2 was cancelled!
I suggest you to divide your problem into 2 separate ones:
run on multiple threads
use a timeout for each operation
For the first (multithreading), you already used the service executor that can manage that on 2 Threads : Executors.newFixedThreadPool(2). If you apply the timeout here, the timeout act for the run of all tasks, but you need a timeout for each job.
For the timout issue, you can manage it thanks to a new service executor per job in a class: JobManager.
package com.stackoverflow.q24473796;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class JobManager implements Callable<Integer> {
protected long timeout;
protected TimeUnit timeUnit;
protected Callable<Integer> job;
public JobManager(long timeout, TimeUnit timeUnit, Callable<Integer> job) {
this.timeout = timeout;
this.timeUnit = timeUnit;
this.job = job;
}
#Override
public Integer call() {
Integer result = new Integer(-1); // default, this could be adapted
ExecutorService exec = Executors.newSingleThreadExecutor();
try {
result = exec.submit(job).get(timeout, timeUnit);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
// Whatever you want
if (e instanceof TimeoutException) {
System.out.println("Timeout get for " + job.toString());
} else {
System.out.println("exception get for " + job.toString() + " : " + e.getMessage());
}
}
exec.shutdown();
return result;
}
}
Then, you can call the tasks from your main thread as following:
Job job = new Job(i * 1000, i);
Future<Integer> future = newFixedThreadPool.submit(new JobManager(5, TimeUnit.SECONDS, job));
I addapted your CallableTest:
package com.stackoverflow.q24473796;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class CallableTest {
public static void main(String[] args) {
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);
List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
for (int i = 10; i > 0; i--) {
Job job = new Job(i * 1000, i);
Future<Integer> future = newFixedThreadPool.submit(new JobManager(5, TimeUnit.SECONDS, job));
futures.add(future);
}
ArrayList<Integer> results = new ArrayList<Integer>();
for (Future<Integer> future : futures) {
Integer result = new Integer(-1);
try {
result = future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
if (result != -1) {
results.add(result);
}
}
newFixedThreadPool.shutdown();
try {
newFixedThreadPool.awaitTermination(60, TimeUnit.SECONDS); //Global Timeout
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(new Date() + " results:");
for (int j : results) {
System.out.println(new Date() + " " + j);
}
}
}
And you'll get the following output:
Wed Apr 29 10:51:02 CEST 2015 10 started
Wed Apr 29 10:51:02 CEST 2015 9 started
Timeout get for com.stackoverflow.q24473796.Job#249fe45c
Timeout get for com.stackoverflow.q24473796.Job#249fe45c
Wed Apr 29 10:51:07 CEST 2015 8 started
Wed Apr 29 10:51:07 CEST 2015 7 started
Wed Apr 29 10:51:11 CEST 2015 9 finished
Timeout get for com.stackoverflow.q24473796.Job#3cd4c5a0
Timeout get for com.stackoverflow.q24473796.Job#3cd4c5a0
Wed Apr 29 10:51:12 CEST 2015 6 started
Wed Apr 29 10:51:12 CEST 2015 5 started
Wed Apr 29 10:51:12 CEST 2015 10 finished
Wed Apr 29 10:51:14 CEST 2015 7 finished
Wed Apr 29 10:51:15 CEST 2015 8 finished
Wed Apr 29 10:51:17 CEST 2015 5 finished
Wed Apr 29 10:51:17 CEST 2015 4 started
Timeout get for com.stackoverflow.q24473796.Job#2a0fded2
Wed Apr 29 10:51:17 CEST 2015 3 started
Wed Apr 29 10:51:18 CEST 2015 6 finished
Wed Apr 29 10:51:20 CEST 2015 3 finished
Wed Apr 29 10:51:20 CEST 2015 2 started
Wed Apr 29 10:51:21 CEST 2015 4 finished
Wed Apr 29 10:51:21 CEST 2015 1 started
Wed Apr 29 10:51:22 CEST 2015 1 finished
Wed Apr 29 10:51:22 CEST 2015 2 finished
Wed Apr 29 10:51:22 CEST 2015 results:
Wed Apr 29 10:51:22 CEST 2015 5
Wed Apr 29 10:51:22 CEST 2015 4
Wed Apr 29 10:51:22 CEST 2015 3
Wed Apr 29 10:51:22 CEST 2015 2
Wed Apr 29 10:51:22 CEST 2015 1
You've got Jobs running on two threads and you're reading results from your main thread. While you're waiting for one Job to finish, another Job is running without you waiting. I think you'll find you get the results you expect if you change your thread pool to a size of 1.
If you have to run the jobs on multiple threads, you'll have to come up with a way to track how long a Job has already been running by the time you start waiting for a result. If the Job has already been running for longer than 5 seconds, reject it. If not, wait for 5 seconds minus the amount of time it's already been running.
One option would be to store the start time in the Job. Then you could do something like
long elapsedTime = System.currentTimeMillis() - job.getStartTime();
if (elapsedTime < 5000) {
future.get(5000 - elapsedTime, TimeUnit.MILLISECONDS);
}
You can use a ScheduledExecutorService for this. First you would submit each task and retain the futures that are created. After that you can submit a new task that would cancel the retained future after some period of time.
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
for (int i = 10; i > 0; i--) {
Job job = new Job(i * 1000, i);
final Future handler = executor.submit(job);
executor.schedule(new Runnable(){
public void run(){
handler.cancel();
}
}, 5000, TimeUnit.MILLISECONDS);
futures.add(handler);
}
This will execute your handler (main functionality to be interrupted) for 5 seconds, then will cancel (i.e. interrupt) that specific task.
At this point you know that no Job will be allowed to run for more than 5 seconds, so
Integer content = future.get(5, TimeUnit.SECONDS);
Should work fine.
Probably the best way is to handle the timing from within the Callable's call() method. When you enter the method, record the time. Split up the time within the call() method - in the example case, instead of sleeping for the full time, sleep for one second at a time - and each time through, check whether the maximum time has elapsed since the entry time. If it has, abort processing and exit gracefully.
If you absolutely cannot have the Callable's code check periodically on the time - or on an external stop notification, as others have suggested - there is one way to terminate it from code executing outside the thread. However, this way is deprecated because it is almost certain to cause unfixable bugs. Essentially, when the thread starts - that is, when the call() method is entered - start a TimerTask subclass and give it a pointer to the thread. When the TimerTask fires, it calls Thread.stop() on the thread. Again, this is highly unsafe, because it is likely to leave objects in a corrupted state, as explained in the Oracle documentation here:
http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
About the only way this could work is if your Callable's code never needs to synchronize and never actually synchronizes on any object, even within a library call, and will never be changed in the future to do so. This is extremely difficult to ensure, so it would be much better to figure out a way to break up the Callable's code so it could check on the time periodically and exit gracefully if it times out.
One final note: if you really think your Callable's code never needs to synchronize to share objects in memory, it's a great candidate for execution in an external process, rather than in a thread in the main process. The advantage to this is that you can kill an external process relatively safely. Basically, the TimerTask in the external process would call System.exit() in the worker process rather than Thread.stop() in the worker thread.

count number of certain value occurances in a string

I have a string which contains my mail details such as
GitHub Sat Jun 01 13:32:02 IST 2013
eBay Mon Jun 03 17:37:40 IST 2013
YouTube Tue Jun 04 00:18:50 IST 2013
YouTube Sat Jun 08 01:20:47 IST 2013
eBay Sat Jun 08 13:19:22 IST 2013
eBay Sat Jun 08 13:17:53 IST 2013
eBay Mon Jun 10 15:43:01 IST 2013
YouTube Mon Jun 10 15:47:02 IST 2013
eBay Wed Jun 12 11:10:15 IST 2013
eBay Wed Jun 12 19:25:50 IST 2013
eBay Thu Jun 13 17:22:14 IST 2013
eBay Thu Jun 13 18:09:18 IST 2013
Clark University Thu Jun 13 19:30:09 IST 2013
is there any way to get number of times eBay ,Youtube or anything has occured so that i can have a number of mails received from a particular person??
You can split the string using String tokenizer and match the value of first token.
If eBay is always going to be the first word then, you can use startsWith() method of String class.
try to use regular expressions with grouping of data.
This solution supposes two things:
names of days cannot appear in the first part;
each entry is separated by a newline:
[extra line to fix SO bug with list items and code extracts]
private static final Set<String> DAYS = new HashSet<String>(Arrays.asList(
"Mon ", "Tue ", "Wed ", "Thu ", "Fri ", "Sat ", "Sun "
));
public int nrMatches(final String mailList, final String sender)
{
int ret = 0;
int index;
for (final String line: mailList.split("\r?\n"))
for (final String day: DAYS) {
index = line.indexOf(day);
if (index == -1)
continue;
if (line.subString(0, index).trim().equals(sender))
ret++;
}
return ret;
}

Categories

Resources