×
Namespaces

Variants
Actions
(Difference between revisions)

Synchronising resource access in Java ME

From Nokia Developer Wiki
Jump to: navigation, search
namesan (Talk | contribs)
tapla (Talk | contribs)
Line 356: Line 356:
  
 
</code>
 
</code>
 
  
 
==Postconditions==
 
==Postconditions==
  
 
Text field, "synchronizing" checkbox and logging text box are placed on display. By pressing "Execute snippet" user starts threads which write their characters to string in synchronized way and one other thread - which returns this string in text field placed on form.
 
Text field, "synchronizing" checkbox and logging text box are placed on display. By pressing "Execute snippet" user starts threads which write their characters to string in synchronized way and one other thread - which returns this string in text field placed on form.
 
  
 
==Supplementary material==
 
==Supplementary material==
  
* You can test the threads synchronozation in action in a simple, executable application into which this code snippet has been patched. The executables and source files are available for download at: [[Media:SynchronizingResourceAccess.zip]].
+
This code snippet is part of the stub concept, which means that it has been patched on top of a template application in order to be more useful for developers. The version of the Java ME stub application used as a template in this snippet is v1.1.
  
* You can examine all the changes that are required to implement the above mentioned features in an application. The changes are provided in unified diff and color-coded diff formats: [[link_to_patchs]]
+
* The patched, executable application that can be used to test the features described in this snippet is available for download at [[Media:SynchronizingResourceAccess.zip]].
 +
* You can view all the changes that are required to implement the above-mentioned features. The changes are provided in unified diff and colour-coded diff (HTML) formats in [[Media:SynchronizingResourceAccess.diff.zip]].
 +
* For general information on applying the patch, see [[Using Diffs]].
 +
* For unpatched stub applications, see [[Example stub]].
  
 
[[Category:Java ME]][[Category:Code Examples]]
 
[[Category:Java ME]][[Category:Code Examples]]

Revision as of 16:53, 23 March 2009


Article Metadata
Tested with
Devices(s): Nokia E70, Nokia 5800 XM, Nokia 6021, Nokia 6131
CompatibilityArticle
Keywords: synchronized, java.lang.Thread, java.lang.Runnable, java.lang.Runnable.run, java.lang.Thread.start, java.lang.Thread.join, java.lang.Thread.isAlive
Created: (28 Jan 2009)
Last edited: tapla (23 Mar 2009)


Overview

This code snippet demonstrates how to create and execute several threads and synchronize their access to some resource.

Because a context switch can occur at any time, the newly running thread can find itself reading data that a previously running thread was not completed writing. Interacting threads must use thread synchronization to control - who can read or write shared data at any moment of time.

Thread synchronization depends on a construct called a monitor. A monitor acts as a gatekeeper, ensuring that only one thread at current moment of time has access to data. Whenever a thread needs to access protected data, it asks the monitor to lock the data for its own use. Other threads interested for the same data are forced to wait until the data will be unlocked.After that the monitor will lock the data for one of the waiting threads and allow it to proceed with its processing.

Any Java object can act as a monitor to control access to data using the synchronized keyword.

In this snippet resource shared between threads is the StringContainer class. It contains string and addLetter() method which adds specified character to string three times. Also is has synchronized version of this method named addLetterSync(). This method consist of synchronized block which insures that only one thread can execute this block updating string at current moment. In this case current thread adds to string exactly three specified characters before any other thread can write to string. To switch between executing of synchronized and non-synchronized version of addLetter by thread user can press "synchronizing" checkbox on main form. In case then addLetterSync() is executing different letters appears in text field exactly three times. Then addLetter is executing different letters appears in text field in random order.

In this snippet three threads write their characters to string - which contains in StringContainer class - and one other thread returns this string into text field placed on a form. All these thread operations are performed in synchronized or non-synchronized way depending on "synchronizing" checkbox.


This midlet consists of 4 source files:

  1. SynchronizingMidlet.java - contains midlet class.
  2. StringContainer.java - contains resource class shared between threads.
  3. AddCharThread.java - contains thread class for updating string container.
  4. OutputStringThread.java - contains thread class for showing string container state to the user.

Source file: SynchronizingMidlet.java

    // Text field contains output from string container
private TextField textField;
 
// Access synchronization choise group
private ChoiceGroup syncTypeChoise;
 
// String container to be updated by threads
private StringContainer stringContainer;
// Array of threads which updates string container
private Vector threads;
// Thread which returns and stores state of string container
private OutputStringThread outputThread;
 
/**
* Sets up the main form.
*/

private void setupMainForm() {
mainForm = new Form("Synchronizing resource access");
 
...
 
// Create list box for synchronized type
syncTypeChoise = new ChoiceGroup("",
ChoiceGroup.MULTIPLE);
syncTypeChoise.append("synchronize", null);
syncTypeChoise.setSelectedIndex(0, true);
 
mainForm.append(syncTypeChoise);
 
mainForm.setItemStateListener(this);
 
...
}
 
/**
* Executes the snippet.
*/

private void executeSnippet() {
stringContainer = new StringContainer(15);
startThreads();
}
 
/**
* Closes the opened resources and exits the application.
*/

private void exit() {
stopThreads();
 
...
 
notifyDestroyed();
}
 
 
/**
* Starts threads for updating string container and sending it state
* to text field.
*/

private void startThreads() {
// Stop threads if they are already running
stopThreads();
 
// Get new value of sync ops flag
boolean useSyncOps = syncTypeChoise.isSelected(0);
 
// Create threads for updating string container. Each thread will write
// to string container one of chars from array below three times.
char[] chars = {'a', 'b', 'c'};
threads = new Vector(chars.length);
for(int n = 0; n < chars.length; n++) {
AddCharThread thread = new AddCharThread(stringContainer, chars[n]);
thread.setUseSyncOperations(useSyncOps);
threads.addElement(thread);
thread.start();
}
 
// Create thread for output
outputThread = new OutputStringThread(textField, stringContainer);
outputThread.start();
}
 
/**
* Stops all threads.
*/

private void stopThreads() {
// Stop update threads
if(threads != null) {
for(int n = 0; n < threads.size(); n++) {
AddCharThread thread = (AddCharThread)threads.elementAt(n);
if(thread != null && thread.isAlive() == true) {
thread.quit();
try {
thread.join();
} catch(InterruptedException exc) {
// This thread was interrupted, do nothing.
}
}
}
 
threads.removeAllElements();
}
 
// Stop output thread
if(outputThread != null && outputThread.isAlive() == true) {
outputThread.quit();
try {
outputThread.join();
} catch(InterruptedException exc) {
// This thread was interrupted, do nothing.
}
}
}
 
/**
* From ItemStateListener.
* Called when internal state of an Item has been changed by the user.
* @param item the item that was changed
*/

public void itemStateChanged(Item item) {
if(item == syncTypeChoise) {
// Get new value of flag
boolean useSyncOps = syncTypeChoise.isSelected(0);
 
// Set new value to all char threads
int threadCount = threads.size();
for(int n = 0; n < threadCount; n++) {
AddCharThread thread = (AddCharThread)threads.elementAt(n);
thread.setUseSyncOperations(useSyncOps);
}
}
}


Source file: StringContainer.java

/**
* This class contains string and some synchronized operations for it.
*/

public class StringContainer {
// String buffer contains string
private StringBuffer stringBuffer;
// Max length of the string
private int maxLength;
 
/**
* Constructor
* @param maxLength - max length of the string in container.
*/

public StringContainer(int maxLength) {
this.maxLength = maxLength;
stringBuffer = new StringBuffer();
}
 
/**
* Adds specified character to the end of string three times.
* If length of string exceeding max length then characters from begin
* of string will be removed.
* This method is not syncronized.
* @param ch - character for updating string.
*/

public void addLetter(char ch) {
// Add character to buffer
for(int n = 0; n < 3; n++) {
stringBuffer.append(ch);
// If buffer length exceed max length then cut it
if(stringBuffer.length() > maxLength) {
stringBuffer.deleteCharAt(0);
}
}
}
 
/**
* Adds specified character to the end of string three times.
* This method is a syncronized version of addLetter method.
* @param ch - character for updating string.
*/

public void addLetterSync(char ch) {
synchronized(stringBuffer) {
addLetter(ch);
}
}
 
/**
* Returns string from this container. This method is not synchronized.
* @return string from this container.
*/

public String toString() {
return stringBuffer.toString();
}
 
/**
* Returns string from this container. This method is synchronized version
* of toString method.
* @return string from this container.
*/

public String toStringSync() {
synchronized(stringBuffer) {
return toString();
}
}
}

Source file: AddCharThread.java

/**
* AddCharThread class.
* Adds character to specified string container.
*/

public class AddCharThread extends Thread {
// String container to be updated
private StringContainer stringContainer;
// Character for updating string container
private char ch;
// Flag indicating that thread must quit.
private boolean isQuit = false;
 
// Flag indicating using synchronized operations of stringContainer or not.
// Type of this class member is Boolean instead of boolean. It is done for
// synchronized purposes since only reference types can be synchronized.
private Boolean bUseSyncOperations = Boolean.TRUE;
 
/**
* Constructor.
* @param stringContainer - resource to be updated
* @param ch - character for updating string container
*/

public AddCharThread(StringContainer stringContainer, char ch) {
this.stringContainer = stringContainer;
this.ch = ch;
}
 
/**
* Sets flag indicating using synchronized operations of stringContainer
* or not.
* @param bUse if true - use synchronized operations.
*/

public void setUseSyncOperations(boolean bUse) {
synchronized(bUseSyncOperations) {
bUseSyncOperations = new Boolean(bUse);
}
}
 
/**
* Gets flag indicating using synchronized operations of stringContainer
* or not.
* @return
*/

private boolean getUseSyncOperations() {
synchronized(bUseSyncOperations) {
return bUseSyncOperations.booleanValue();
}
}


Source file: OutputStringThread.java

import javax.microedition.lcdui.TextField;
 
/**
* OutputStringThread class
* Output current state of specified string container to the text field.
*/

public class OutputStringThread extends Thread {
// Text field for storing output string container state
private TextField textField;
// String container to store its state
private StringContainer stringContainer;
// Indicates if this thread must be terminated
private boolean isQuit = false;
 
/**
* Constructor.
* @param textField - text field for storing output string container state
* @param container - string container for storing its state
*/

public OutputStringThread(TextField textField, StringContainer container) {
this.textField = textField;
this.stringContainer = container;
}
 
/**
* Terminates thread.
*/

public void quit() {
isQuit = true;
}
 
/**
* From Thread class.
* Implements thread functionality.
*/

public void run() {
// If something is not assigned then exit thread
if(textField == null || stringContainer == null) {
return;
}
 
// Thread main loop
while(isQuit == false) {
// Store into text field state of string container
textField.setString(stringContainer.toStringSync());
// Sleep for a 200 milliseconds
try {
sleep(200);
} catch(InterruptedException exc) {
// Thread was interrupted
return;
}
}
}
}

Postconditions

Text field, "synchronizing" checkbox and logging text box are placed on display. By pressing "Execute snippet" user starts threads which write their characters to string in synchronized way and one other thread - which returns this string in text field placed on form.

Supplementary material

This code snippet is part of the stub concept, which means that it has been patched on top of a template application in order to be more useful for developers. The version of the Java ME stub application used as a template in this snippet is v1.1.

79 page views in the last 30 days.