Guava RateLimiter to control the frequency of events

5 09 2015

Having a long running process, consisting of many small, fast steps, updating its listeners after processing each step?

Assume that you process the list of thousands items in a thread and want to show each processed item to the user. Processing each item is very fast, so the updates will be send to the GUI very frequently. You do not want to notify the GUI listener so often. But you want to refresh the gui twice per second, not more.

This is what RateLimiter can do: limit the access to the resources to prevent too frequent calls.

GuiUpdater

For sake of simplicity my GuiUpdater just prints message with a timestamp on System.out:

public class ProgressGuiUpdater implements GuiUpdater{
    @Override
    public void updateGui(String message) {
        System.out.println(LocalDateTime.now().toLocalTime() + ": " + message);
    }
}

The LongRunningProcess

My process consists of many small steps. In each step I update the GUI via the injected updater. Calling this loop with 15000 iterations lasts around 3 seconds.

@Override
public void run() {
    for (int i = 0; i < stepsCount; i++) {
        guiUpdater.updateGui("This is the item number" + i);
    }
}

GUI gets updated around 5000 times per second. For average app it is way too often. This is the fragment of console output (mind the timestamps):

16:53:10.025: This is item number 1
16:53:10.026: This is item number 2
16:53:10.026: This is item number 3
16:53:10.027: This is item number 4
16:53:10.027: This is item number 5
16:53:10.028: This is item number 6
16:53:10.029: This is item number 7

Limit the updates frequency

RateLimiter will limit the access to the updater. It will stop the thread execution until the specified time will pass (remember the semaphores in Java?). After it will acquire the access, the thread will be unblocked and updater method will be called. Before calling the updater method I need to acquire the RateLimiter:

@Override
public void run() {
    for (int i = 0; i < stepsCount; i++) {
        double waitTime = rateLimiter.acquire();
        guiUpdater.updateGui("This is the item number " + i + " (I've waited for acquire for " + waitTime + " seconds)");
    }
}

The creation of rateLimiter is:

RateLimiter.create(2.0)

As a parameter I pass the number of times per second the rate limiter can acquire the lock.

The result of that configuration is (mind the timestamps and waiting times):

18:09:15.364: This is the item number 0 (I've waited for acquire for 0.0 seconds)
18:09:15.539: This is the item number 1 (I've waited for acquire for 0.113705 seconds)
18:09:16.028: This is the item number 2 (I've waited for acquire for 0.486599 seconds)
18:09:16.527: This is the item number 3 (I've waited for acquire for 0.498785 seconds)
18:09:17.027: This is the item number 4 (I've waited for acquire for 0.498922 seconds)
18:09:17.527: This is the item number 5 (I've waited for acquire for 0.49909 seconds)
18:09:18.027: This is the item number 6 (I've waited for acquire for 0.499802 seconds)
18:09:18.529: This is the item number 7 (I've waited for acquire for 0.499185 seconds)
18:09:19.034: This is the item number 8 (I've waited for acquire for 0.496844 seconds)
18:09:19.527: This is the item number 9 (I've waited for acquire for 0.492872 seconds)

That’s it! Get the source code
Source code for this demo is on my github: https://github.com/yacekmm/looksok/tree/RateLimiterDemo/Guava/RateLimiter

Advertisements




Android status bar notifications [complete tutorial with source code]

1 02 2014

Displaying status bar notification is a common way to unobtrusively inform user that something has happened (like new GMail message notification). In your app you can display it whenever you want. I will guide you how to do it from basics. This is how notifications are presented to the user:

Status bar notifications

Status bar notifications

Google’s documentation regarding the notifications is here.

Source Code

All the source code for this tutorial you can download here.

1. Create Basic notification

Notification consists of three obligatory parameters: title text, content text and small icon image. Here is the code that creates such notification:

private Notification createBasicNotification() {
	NotificationCompat.Builder builder = new Builder(getApplicationContext());
	Notification notification = builder
			.setSmallIcon(R.drawable.me)
			.setContentTitle(getString(R.string.notif_title))
			.setContentText(getString(R.string.notif_text))
			.build();

	return notification;
}

2. Display Basic Notification

After it is built, you can display it to the user with NotificationManager:

private void displayNotification(Notification notification) {
	NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
	notificationManager.notify(myNotificationId , notification);
}

Where myNotificationId is final int and is equal to 1:

private static final int myNotificationId = 1;

Thanks to this ID later you can refer to that notification and update its content  or hide it when you need it.

This is how the notification looks like right now:

notif_my_custom

3. Auto Hide notification after it is touched

As for now nothing happens when user touches notification. To make it disappear after touch add this clause to the builder:

setAutoCancel(true)

4. Start activity after notification is touched

The most common action after user selects notification is to open activity presenting the detailed data that caused notification to be issued. You have to assign PendingIntent to notification in order to do it:

private PendingIntent preparePendingIntent() {
	Intent intent = new Intent(getApplicationContext(), MainActivity.class);
	intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

	PendingIntent pendingIntent = PendingIntent.getActivity(
			getApplicationContext(), 
			0, 
			intent, 
			PendingIntent.FLAG_UPDATE_CURRENT);
	return pendingIntent;
}

After that, you assign this intent to notification with the builder command:

.setContentIntent(notificationIntent)

Now you have a basic notification that can issue certain action. Further customization is optional and introduced in newer versions of Android. Since possibilities are quite big, it is worth to continue improving the notification.

5. Filling in remaining small notification fields

Here is the code to fill in the remaining fields of small notification (this should be called on bilder object):

.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.me))
.setContentInfo(getString(R.string.notif_contentInfo))
.setWhen(Calendar.getInstance().getTimeInMillis() + 1000*60+60)
.setVibrate(vibrationPattern)

In order to make vibrations work you need to define pattern (mine is quite sophisticated :P):

long[] vibrationPattern = {0, 200, 800, 200, 600, 200, 400, 200, 200, 200, 100, 200, 50, 200, 50, 200, 50, 200, 500, 200};

but it surely can be simplier:

// Start without a delay
// Vibrate for 100 milliseconds
// Sleep for 1000 milliseconds
long[] pattern = {0, 100, 1000};

and require an VIBRATE permission in android manifest

<uses-permission android:name="android.permission.VIBRATE"/>

6. Apply big style to the notification

What actually is the Big Style? It is the notification with list of String. This is so called InboxStyle, since it is mainy used by GMail to notify user of incoming list of messages. This is how it looks like:

Notice that most of the elements are the same, except the 7 – the details list. Remember that big style works only for android versions higher than or equal to 4.2.

So now – how to build this list? Just create the notificationas it is done until now, and apply style to the builder:

.setStyle(inboxStyle)

And the inboxStyle is built like this:

private InboxStyle prepareBigNotificationDetails() {
	NotificationCompat.InboxStyle result = new InboxStyle();
	result.setBigContentTitle(getString(R.string.notif_inboxStyleTitle));
	result.addLine(getString(R.string.notif_inboxStyle_line1));
	result.addLine(getString(R.string.notif_inboxStyle_line2));
	result.addLine(getString(R.string.notif_inboxStyle_line3));
	result.addLine(getString(R.string.notif_inboxStyle_line4));
	result.addLine(getString(R.string.notif_inboxStyle_line5));
	result.addLine(getString(R.string.notif_inboxStyle_line6));
	return result;
}

Now test it (remember that only android 4.2 or higher will handle such notification). The result is like this:

InboxStyle notification

InboxStyle notification

notice that fields displayed on small notification are not visible in this style.

7. Updating notification content

Notification updates are quite simple: just set the fields you want to change with notification builder and call NotificationManagers’ notify() method providing the ID that you assigned to the notification that you need to update. The notification will be updated accordingly.

Download the Source Code

All the source code for this tutorial you can download here.

Did I help you?
I manage this blog and share my knowledge for free, sacrificing my time. If you appreciate it and find this information helpful, please consider making a donation in order to keep this page alive and improve quality

Donate Button with Credit Cards

Thank You!





iOS: Timer countdown implementation tutorial (including source code)

29 12 2012

This lesson shows how to build timed periodic updates in iOS app using NSTimer. In my example I update timer value in text label. GUI consists of one label and one button. Button press starts the timer countdown.

Timer app GUI captions

Timer app GUI captions

1. Create NSTimer instance

I use timer variable that holds reference to NSTimer object. Timer is then handled using iOS notifications in ViewController:

timer = [NSTimer scheduledTimerWithTimeInterval:1.0
	target:self
	selector:@selector(updateLabel:)
	userInfo:nil
	repeats:YES ];

Here the interval is set (in seconds) and the repeats flag. Target is set to self (ViewController) to the updateLabel: method. Timer is started instantly after initialization.

2. Define updater method

The updateLabel:sender will be called by iOS notification every time, when timer interval will pass. Here you can put custom code that is required by your app logic.

My logic simply increases counter value and updates text label with the new counter value. I also check if counter does not exceed MAX_VALUE. if it does, I invalidate the timer (see next point to see how to invalidate timer).

- (void)updateLabel:(id)sender{
	if(counterValue &gt;= MAX_VALUE){
		[self killTimer];
	}
	self.counterLabel.text = [NSString stringWithFormat:@"%d", counterValue];
	counterValue++;
}

3. How to stop repeatable timer?

If you set your timer to repeatable, it will be repeating infinitely. To stop it you need to invalidate it. I also set it to nil. I use killTimer: method that handles it:

- (void)killTimer{
	if(timer){
		[timer invalidate];
		timer = nil;
	}
}

Be careful: invalidating timer that was already invalidated will cause application to crash! This is why I check if timer is not nil before invalidating it.

4. Download my source code

If the tutorial is not enough for you, here is the source code for header and implementation file.

Did I help you?
I manage this blog and share my knowledge for free sacrificing my time. If you appreciate it and find this information helpful, please consider making a donation in order to keep this page alive and improve quality

Donate Button with Credit Cards

Thank You!








%d bloggers like this: