×
Namespaces

Variants
Actions
(Difference between revisions)

Synchronising resource access in Java ME

From Nokia Developer Wiki
Jump to: navigation, search
copyeditor (Talk | contribs)
hamishwillee (Talk | contribs)
m (Hamishwillee - Tidy categories)
(13 intermediate revisions by 5 users not shown)
Line 1: Line 1:
__NOTOC__
+
[[Category:Java ME]][[Category:Threading]][[Category:Files/Data]][[Category:Symbian]][[Category:Series 40]][[Category:Code Examples]][[Category:Java Runtime 2.3 for Symbian]]
__NOEDITSECTION__
+
{{Abstract|This code snippet demonstrates how to create and execute several threads and synchronise their access to a resource.}}
{{KBCS}}
+
 
{{CodeSnippet
+
{{ArticleMetaData <!-- v1.2 -->
|id=CS001320
+
|sourcecode= [[Media:SynchronizingMidletSource.zip]]
|platform=S60 3rd Edition, S60 5th Edition, S40 2nd Edition, S40 3rd Edition, FP 1
+
|installfile= [[Media:SynchronizingMidletBinaries.zip]]
|devices=Nokia E70, Nokia 5800 XM, Nokia 6021, Nokia 6131
+
|devices= Nokia E70, Nokia 5800 XpressMusic, Nokia 6021, Nokia 6131, Nokia 701, Nokia Asha 305
|category=Java ME
+
|sdk= [http://www.developer.nokia.com/Develop/Java/Tools/ Nokia SDK 1.1 for Java],  [http://www.developer.nokia.com/Develop/Java/Tools/ Nokia SDK 2.0 for Java]
|subcategory=Base/System
+
|platform= Series 40, Symbian
|creationdate=January 28, 2009
+
|devicecompatability= <!-- Compatible devices (e.g.: All* (must have GPS) ) -->
|keywords=synchronized, java.lang.Thread, java.lang.Runnable, java.lang.Runnable.run, java.lang.Thread.start, java.lang.Thread.join, java.lang.Thread.isAlive
+
|dependencies= <!-- Any other/external dependencies e.g.: Google Maps Api v1.0 -->
 +
|signing= <!-- Empty or one of Self-Signed, DevCert, Manufacturer -->
 +
|capabilities= <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. -->
 +
|keywords= synchronized, java.lang.Thread, java.lang.Runnable, java.lang.Runnable.run, java.lang.Thread.start, java.lang.Thread.join, java.lang.Thread.isAlive
 +
|language= <!-- Language category code for non-English topics - e.g. Lang-Chinese -->
 +
|translated-by= <!-- [[User:XXXX]] -->
 +
|translated-from-title= <!-- Title only -->
 +
|translated-from-id= <!-- Id of translated revision -->
 +
|review-by= <!-- After re-review: [[User:username]] -->
 +
|review-timestamp= <!-- After re-review: YYYYMMDD -->
 +
|update-by= <!-- After significant update: [[User:username]]-->
 +
|update-timestamp= <!-- After significant update: YYYYMMDD -->
 +
|creationdate= 20090226
 +
|author= [[User:Dekudin]]
 +
<!-- The following are not in current metadata -->
 +
|id= CS001320
 
}}
 
}}
 
 
 
==Overview==
 
==Overview==
 
This code snippet demonstrates how to create and execute several threads and synchronise their access to a resource.
 
  
 
Because a context switch can occur at any time, a new running thread can find itself reading data that a previous running thread has not yet finished writing. Interacting threads must use thread synchronisation in order to control which thread can read or write shared data at any given moment.
 
Because a context switch can occur at any time, a new running thread can find itself reading data that a previous running thread has not yet finished writing. Interacting threads must use thread synchronisation in order to control which thread can read or write shared data at any given moment.
Line 21: Line 32:
 
Thread synchronisation depends on a construct called a monitor. The monitor acts as a gatekeeper, ensuring that only one thread at a time has access to specific data. Whenever a thread needs to access protected data, it asks the monitor to lock the data for its use. Other threads trying to access the same data are forced to wait until the data is unlocked. After that, the monitor will lock the data for one of the waiting threads and allow it to proceed with its processing.
 
Thread synchronisation depends on a construct called a monitor. The monitor acts as a gatekeeper, ensuring that only one thread at a time has access to specific data. Whenever a thread needs to access protected data, it asks the monitor to lock the data for its use. Other threads trying to access the same data are forced to wait until the data is 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 <tt>synchronized</tt> keyword.
+
Any Java object can act as a monitor to control access to data using the {{Icode|synchronized}} keyword.
  
In this snippet, the resource shared between threads is the <tt>StringContainer</tt> class. It contains a string and the <tt>addLetter()</tt> method, which adds a specified character to the string three times. A synchronised version of this method is named <tt>addLetterSync()</tt>. This method consist of a <tt>synchronized</tt> block, which ensures that only one thread can execute this block updating string at a time. In this case, the current thread adds exactly three specified characters to the string before any other thread can write to the string. To switch between executing the synchronised and the non-synchronised version of <tt>addLetter</tt>, the user can press the 'Synchronizing' check box on the main form. When <tt>addLetterSync()</tt> is executing, different letters appear in the text field exactly three times. When <tt>addLetter</tt> is executing, different letters appear in the text field in random order.
+
In this snippet, the resource shared between threads is the {{Icode|StringContainer}} class. It contains a string and the {{Icode|addLetter()}} method, which adds a specified character to the string three times. A synchronised version of this method is named {{Icode|addLetterSync()}}. This method consist of a {{Icode|synchronized}} block, which ensures that only one thread can execute this block updating string at a time. In this case, the current thread adds exactly three specified characters to the string before any other thread can write to the string. To switch between executing the synchronised and the non-synchronised version of {{Icode|addLetter}}, the user can press the 'Synchronizing' check box on the main form. When {{Icode|addLetterSync()}} is executing, different letters appear in the text field exactly three times. When {{Icode|addLetter}} is executing, different letters appear in the text field in random order.
  
 
In this snippet, three threads write their characters to the string  - which is located in the StringContainer class - and one other thread returns this string into a text field placed on a form. All these thread operations are performed in synchronised or non-synchronised way depending on the 'Synchronizing' check box.
 
In this snippet, three threads write their characters to the string  - which is located in the StringContainer class - and one other thread returns this string into a text field placed on a form. All these thread operations are performed in synchronised or non-synchronised way depending on the 'Synchronizing' check box.
 
  
 
This MIDlet consists of 4 source files:
 
This MIDlet consists of 4 source files:
 
 
# SynchronizingMidlet.java - contains the MIDlet class.
 
# SynchronizingMidlet.java - contains the MIDlet class.
 
# StringContainer.java - contains the resource class shared between threads.
 
# StringContainer.java - contains the resource class shared between threads.
 
# AddCharThread.java - contains the thread class for updating the string container.
 
# AddCharThread.java - contains the thread class for updating the string container.
 
# OutputStringThread.java - contains the thread class for showing the string container state to the user.
 
# OutputStringThread.java - contains the thread class for showing the string container state to the user.
 +
  
 
==Source file: SynchronizingMidlet.java==
 
==Source file: SynchronizingMidlet.java==
Line 363: Line 373:
 
A text field, the 'Synchronizing' check box and a logging text box are placed on the display. Press 'Execute snippet' to start the threads which write their characters to the string in a synchronised way, and one other thread which returns this string in the text field placed on the form.
 
A text field, the 'Synchronizing' check box and a logging text box are placed on the display. Press 'Execute snippet' to start the threads which write their characters to the string in a synchronised way, and one other thread which returns this string in the text field placed on the form.
  
==Supplementary material==
+
{{VersionHint}}
 
+
[[Category:S60 3rd Edition (initial release)]] [[Category:S60 3rd Edition FP1]] [[Category:S60 3rd Edition FP2]]
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.
+
[[Category:S60 5th Edition]]
 
+
[[Category:Symbian^3]] [[Category:Symbian Anna]] [[Category:Nokia Belle]]
* The patched, executable application that can be used to test the features described in this snippet is available for download at [[Media:SynchronizingResourceAccess.zip]].
+
[[Category:Series 40 2nd Edition]]  
* 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]].
+
[[Category:Series 40 3rd Edition (initial release)]] [[Category:Series 40 3rd Edition FP1]] [[Category:Series 40 3rd Edition FP2]]  
* For general information on applying the patch, see [[Using Diffs]].
+
[[Category:Series 40 5th Edition (initial release)]] [[Category:Series 40 5th Edition FP1]]  
* For unpatched stub applications, see [[Example stub]].
+
[[Category:Series 40 6th Edition (initial release)]] [[Category:Series 40 6th Edition FP1]] [[Category:Series 40 Developer Platform 1.0]] [[Category:Series 40 Developer Platform 1.1]] [[Category:Series 40 Developer Platform 2.0]]
 
+
[[Category:Java ME]][[Category:Code Examples]]
+

Revision as of 07:31, 2 October 2012

This code snippet demonstrates how to create and execute several threads and synchronise their access to a resource.

Article Metadata
Code ExampleTested with
Devices(s): Nokia E70, Nokia 5800 XpressMusic, Nokia 6021, Nokia 6131, Nokia 701, Nokia Asha 305
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: dekudin (26 Feb 2009)
Last edited: hamishwillee (02 Oct 2012)

Contents

Overview

Because a context switch can occur at any time, a new running thread can find itself reading data that a previous running thread has not yet finished writing. Interacting threads must use thread synchronisation in order to control which thread can read or write shared data at any given moment.

Thread synchronisation depends on a construct called a monitor. The monitor acts as a gatekeeper, ensuring that only one thread at a time has access to specific data. Whenever a thread needs to access protected data, it asks the monitor to lock the data for its use. Other threads trying to access the same data are forced to wait until the data is 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, the resource shared between threads is the StringContainer class. It contains a string and the addLetter() method, which adds a specified character to the string three times. A synchronised version of this method is named addLetterSync(). This method consist of a synchronized block, which ensures that only one thread can execute this block updating string at a time. In this case, the current thread adds exactly three specified characters to the string before any other thread can write to the string. To switch between executing the synchronised and the non-synchronised version of addLetter, the user can press the 'Synchronizing' check box on the main form. When addLetterSync() is executing, different letters appear in the text field exactly three times. When addLetter is executing, different letters appear in the text field in random order.

In this snippet, three threads write their characters to the string - which is located in the StringContainer class - and one other thread returns this string into a text field placed on a form. All these thread operations are performed in synchronised or non-synchronised way depending on the 'Synchronizing' check box.

This MIDlet consists of 4 source files:

  1. SynchronizingMidlet.java - contains the MIDlet class.
  2. StringContainer.java - contains the resource class shared between threads.
  3. AddCharThread.java - contains the thread class for updating the string container.
  4. OutputStringThread.java - contains the thread class for showing the 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

A text field, the 'Synchronizing' check box and a logging text box are placed on the display. Press 'Execute snippet' to start the threads which write their characters to the string in a synchronised way, and one other thread which returns this string in the text field placed on the form.

Version Hint

Windows Phone: [[Category:Windows Phone]]
[[Category:Windows Phone 7.5]]
[[Category:Windows Phone 8]]

Nokia Asha: [[Category:Nokia Asha]]
[[Category:Nokia Asha Platform 1.0]]

Series 40: [[Category:Series 40]]
[[Category:Series 40 1st Edition]] [[Category:Series 40 2nd Edition]]
[[Category:Series 40 3rd Edition (initial release)]] [[Category:Series 40 3rd Edition FP1]] [[Category:Series 40 3rd Edition FP2]]
[[Category:Series 40 5th Edition (initial release)]] [[Category:Series 40 5th Edition FP1]]
[[Category:Series 40 6th Edition (initial release)]] [[Category:Series 40 6th Edition FP1]] [[Category:Series 40 Developer Platform 1.0]] [[Category:Series 40 Developer Platform 1.1]] [[Category:Series 40 Developer Platform 2.0]]

Symbian: [[Category:Symbian]]
[[Category:S60 1st Edition]] [[Category:S60 2nd Edition (initial release)]] [[Category:S60 2nd Edition FP1]] [[Category:S60 2nd Edition FP2]] [[Category:S60 2nd Edition FP3]]
[[Category:S60 3rd Edition (initial release)]] [[Category:S60 3rd Edition FP1]] [[Category:S60 3rd Edition FP2]]
[[Category:S60 5th Edition]]
[[Category:Symbian^3]] [[Category:Symbian Anna]] [[Category:Nokia Belle]]

142 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×