Unidad IV Acceso a Datos

22
Instituto Tecnológico de Piedras Negras Carrera: Ingeniería en Sistemas Computacionales Tópicos Avanzados de Programación Ing. Wilber Unidad IV Alumno: Abdiel Aníbal Gutiérrez Herrera N° control: 11430324

Transcript of Unidad IV Acceso a Datos

Page 1: Unidad IV Acceso a Datos

Instituto Tecnológico

de Piedras Negras

Carrera: Ingeniería en Sistemas Computacionales

Tópicos Avanzados de Programación

Ing. Wilber

Unidad IV

Alumno: Abdiel Aníbal Gutiérrez Herrera

N° control: 11430324

Índice Unidad IV

Acceso a datos

Page 2: Unidad IV Acceso a Datos

1.1. Introducción 1.2. Creación de una base de datos y tablas1.3. Manipulación de los datos

4.1 Introducción

Acceso a bases de datos (C# y Java)C# y Java utilizan medios similares para obtener acceso a los datos de las bases de datos. Tanto C# como Java requieren que un controlador de bases de datos realice operaciones reales con bases de datos. Además, ambos requieren una conexión con la base de datos, una consulta SQL que se ejecutará en la conexión con la base de datos y un conjunto de resultados procedentes de la ejecución de la consulta.

Comparar controladores de bases de datos

Page 3: Unidad IV Acceso a Datos

Se pueden utilizar controladores de bases de datos, como JDBC u ODBC, para obtener acceso a datos de Java y C#. El controlador JDBC (Java Database Connectivity, conectividad de bases de datos de Java) se utiliza desde un programa escrito en Java. El controlador de ODBC (Open Database Connectivity, Conectividad abierta de bases de datos) es la interfaz de programación de base de datos que utiliza Microsoft para tener acceso a distintas bases de datos relacionales en diversas plataformas. También existe un estándar que sirve de puente entre JDBC-ODBC en las versiones Solaris y Windows de la plataforma Java, para que se pueda utilizar ODBC desde un programa Java.En Java, se proporciona al controlador la información de la cadena de conexión para un identificador de conexión, de la siguiente forma:final static private String url = "jdbc:oracle:server,user,pass, …)";En C#, si se utiliza .NET Framework, no es necesario cargar controladores ODBC ni JDBC para tener acceso a la base de datos. Sólo hay que establecer la cadena de conexión para el objeto de conexión a bases de datos, de la siguiente forma:C#

static string connectionString = "Initial Catalog=northwind;Data Source=(local);Integrated Security=SSPI;";static SqlConnection cn = new SqlConnection(connectionString);

Para obtener más información sobre el controlador ODBC para bases de datos Oracle, vea ODBC Driver for Oracle. Para obtener información adicional sobre el proveedor OLE DB para bases de datos DB2, vea Microsoft Host Integration Server 2000 Developer's Guide y Administration and Management of Data Access Using the OLE DB Provider for DB2.

Microsoft® SQL Server™ 2000 Driver for JDBC  es un controlador JDBC de tipo 4, que proporciona acceso a SQL Server 2000 a través de cualquier subprograma, aplicación o servidor de aplicaciones habilitado para Java.

Ejemplo de lectura de bases de datos de Java

En Java, para realizar una operación de lectura de bases de datos, se puede utilizar un objeto ResultSet creado por el método executeQuery del objetoStatement. El objeto ResultSet contiene los datos devueltos por la consulta. A continuación, puede recorrer en iteración el objeto ResultSet para obtener acceso a los datos.El ejemplo siguiente proporciona el código Java que se va a leer en una base de datos.Connection c;try{ Class.forName (_driver); c = DriverManager.getConnection(url, user, pass);} catch (Exception e) { // Handle exceptions for DriverManager

Page 4: Unidad IV Acceso a Datos

// and Connection creation:}try{ Statement stmt = c.createStatement(); ResultSet results = stmt.executeQuery( "SELECT TEXT FROM dba "); while(results.next()) { String s = results.getString("ColumnName"); // Display each ColumnName value in the ResultSet: } stmt.close();} catch(java.sql.SQLException e){ // Handle exceptions for executeQuery and getString: }Asimismo, para realizar una operación de escritura en la base de datos, se crea un objeto Statement a partir del objeto Connection. El objetoStatement tiene métodos para ejecutar consultas SQL y actualizaciones en una base de datos. Las actualizaciones y consultas se encuentran en una cadena que contiene el comando SQL de una operación de escritura que se utilizó en el método executeUpdate del objeto Statement para devolver un objeto ResultSet.

Ejemplo de lectura de bases de datos de C#

En C#, mediante .NET Framework, el acceso a los datos se simplifica aún más a través del conjunto de clases proporcionado por ADO.NET, que admite el acceso a bases de datos con los controladores ODBC, así como también, a través de proveedores OLE DB. Las aplicaciones de C# pueden interactuar con bases de datos SQL para la lectura, escritura y búsqueda de datos mediante clases ADO.NET de .NET Framework y a través de Microsoft Data Access Component (MDAC). El espacio de nombres y las clases System.Data.SqlClient de .NET Framework facilitan aún más el acceso a las bases de datos de SQL Server.En C#, para realizar una operación de lectura de la base de datos, puede utilizar una conexión, un comando y una tabla de datos. Por ejemplo, para conectarse a una base de datos de SQL Server con el espacio de nombres System.Data.SqlClient, puede utilizar lo siguiente:

Una clase SqlConnection. Una consulta, como una clase SqlCommand. Un conjunto de resultados, como una clase DataTable.

.NET Framework proporciona DataAdapter, que reúne estos tres objetos, de la siguiente forma:

El objeto SqlConnection se establece mediante la propiedad de conexión del objeto DataAdapter.

La consulta que se ejecutará se especifica con la propiedad SelectCommand de DataAdapter.

Page 5: Unidad IV Acceso a Datos

El objeto DataTable se crea utilizando el método Fill del objeto DataAdapter. El objeto DataTable contiene los datos del conjunto de resultados devueltos por la consulta. Puede recorrer en iteración el objeto DataTable para tener acceso a las filas de datos usando la colección de filas.

Para compilar y ejecutar el código, necesita lo que se indica a continuación; de lo contrario, se produce un error en la líneadatabaseConnection.Open(); y se produce una excepción.

Microsoft Data Access Components (MDAC) versión 2.7 o posterior.Si utiliza Microsoft Windows XP o Windows Server 2003, ya dispone de MDAC 2.7. Sin embargo, si utiliza Microsoft Windows 2000, es posible que tenga que actualizar la versión de MDAC instalada en el equipo. Para obtener más información, vea MDAC Installation.

Tener acceso a la base de datos Northwind de SQL Server y privilegios de seguridad integrados para el nombre de usuario actual que ejecuta el código en un servidor SQL Server local con la base de datos de ejemplo Northwind instalada.

C#

// Sample C# code accessing a sample database

// You need:// A database connection// A command to execute// A data adapter that understands SQL databases// A table to hold the result set

namespace DataAccess{ using System.Data; using System.Data.SqlClient;

class DataAccess { //This is your database connection: static string connectionString = "Initial Catalog=northwind;Data Source=(local);Integrated Security=SSPI;"; static SqlConnection cn = new SqlConnection(connectionString);

// This is your command to execute: static string sCommand = "SELECT TOP 10 Lastname FROM Employees ORDER BY EmployeeID";

// This is your data adapter that understands SQL databases: static SqlDataAdapter da = new SqlDataAdapter(sCommand, cn);

// This is your table to hold the result set: static DataTable dataTable = new DataTable();

static void Main() {

Page 6: Unidad IV Acceso a Datos

try { cn.Open();

// Fill the data table with select statement's query results: int recordsAffected = da.Fill(dataTable);

if (recordsAffected > 0) { foreach (DataRow dr in dataTable.Rows) { System.Console.WriteLine(dr[0]); } } } catch (SqlException e) { string msg = ""; for (int i=0; i < e.Errors.Count; i++) { msg += "Error #" + i + " Message: " + e.Errors[i].Message + "\n"; } System.Console.WriteLine(msg); } finally { if (cn.State != ConnectionState.Closed) { cn.Close(); } } } }}

4.2 Creación de una base de datos y tablas

USE masterGOCREATE DATABASE tonysk8shop

Page 7: Unidad IV Acceso a Datos

ON( NAME = tonysk8shop_data,FILENAME = 'C:\PRACTICAS\tonysk8shop_data.mdf',SIZE = 10MB,MAXSIZE = 50MB,FILEGROWTH = 5MB )LOG ON( NAME = DBPractica_log,FILENAME ='C:\PRACTICAS\tonysk8shop_log.ldf',SIZE = 5MB,MAXSIZE = 25MB,FILEGROWTH = 5MB)

CREATE TABLE dbo.Clientes( IDCliente int NOT NULL PRIMARY KEY, Nombre varchar(24) NOT NULL, ApellidoP varchar(50) NOT NULL, APellidoM varchar(50) NOT NULL, Calle varchar(75) NOT NULL, Numero int NOT NULL, Colonia varchar(75) NOT NULL, Telefono int NOT NULL, Edad int NOT NULL, Genero varchar(1) NOT NULL, Facebook varchar(70) NOT NULL, ) CREATE TABLE dbo.Compras( IDCliente int constraint fk_Compras_Cliente foreign key (IDCliente) references dbo.Clientes(IDCliente), ClaveProducto int constraint fk_Productos_Cliente foreign key(ClaveProducto) references dbo.Productos(ClaveProducto),

FolioCompra int NOT NULL PRIMARY KEY,

Fecha date NOT NULL, Cantidad int NOT NULL, PrecioUNitario money NOT NULL, Total money NOT NULL,)

CREATE TABLE dbo.Productos(ClaveProducto int NOT NULL PRIMARY KEY,Marca varchar(30) NOT NULL,Medida float NOT NULL,Precio money NOT NULL,Cantidad int NOT NULL,

Page 8: Unidad IV Acceso a Datos

)

4.3.-MANIPULACIÓN DE LOS DATOS

Lenguaje de Manipulación de Datos (Data Manipulation Language, DML) es un lenguaje proporcionado por el sistema de gestión de base de datos que permite a los usuarios de la misma llevar a cabo las tareas de consulta o manipulación de los datos, organizados por el modelo de datos adecuado. El lenguaje de manipulación de datos más popular hoy día es SQL, usado para recuperar y manipular datos en una base de datos relacional. Otros ejemplos de DML son los usados por bases de datos IMS/DL1, CODASYL u otras.

Son DML: Select, Insert, Delete y Update

Se clasifican en dos grandes grupos:

Lenguajes procedimentales. En este tipo de lenguaje el usuario da instrucciones al sistema para que realice una serie de procedimientos u operaciones en la base de datos para calcular un resultado final.

Lenguajes de consulta no procedimentales. En los lenguajes no procedimentales el usuario describe la información deseada sin un procedimiento específico para obtener esa información.

INSERT

Para introducir datos nuevos en una base de datos vamos a utilizar la orden INSERT de SQL. Con la sintaxis que se muestra a continuación seremos capaces de introducir datos nuevos en cualquiera de las tablas que componen una determinada BD. En principio, veremos la expresión mínima de la orden, formada por dos cláusulas, INTO y VALUES.

INSERT INTO nombreTabla VALUES (listaExpresiones)

DELETE

La sentencia DELETE nos permite borrar las filas contenidas en una tabla.

DELETE [FROM] nombreTabla [WHERE condición]

La sentencia UPDATE nos permite modificar la información contenida en una tabla.

UPDATE

UPDATE nombreTabla [aliasTabla]

SET { {columna=expresion | columna=subconsulta} | listaColumnas=subconsulta}

[WHERE condición]

Page 9: Unidad IV Acceso a Datos

Índice Unidad V

Acceso a datos

Page 10: Unidad IV Acceso a Datos

5.1. Definición conceptual de componentes, paquetes/librerías5.2 Uso de librerías proporcionadas por el lenguaje5.3. Creación y uso de paquetes/librerías definidas por el usuario5.4 Concepto de hilo5.5 Creación y control de hilos5.6 Sincronización de hilos

Page 11: Unidad IV Acceso a Datos

UNIDAD 5 TOPICOS SELECTOS

5.1.-DEFINICION CONCEPTUAL DE COMPONENTES, PAQUETES/LIBRERIAS

Componente: Es una clase abstracta que representa todo lo que tiene una posición, un tamaño, puede ser pintado en pantalla y puede recibir eventos.

Los Objetos derivados de la clase Componente que se incluyen en el Abstract Windows Toolkit son los que aparecen a continuación:

• Button • Canvas • Checkbox • Choice • Label • List • Scrollbar

Container• Panel • Windows o Dialogo FrameTextComponent• TextArea• TextField

Page 12: Unidad IV Acceso a Datos

Un paquete en Java es lo que su nombre lo indica, un paquete o conjunto de clases, lógicamente, que tienen cosas en común. Lógicamente un programado puede agruparlas con o sin criterio, pero lo ideal es que se dediquen a funciones específicas. También los paquetes definen una jerarquía de directorios, que permiten igualmente agrupas las clases, cosa de desplegar los archivos mas ordenadamente.

LIBRERÍAS

La utilización de objetos dinámicos supone dejar pendiente en el montaje de la aplicación el enlace de dichos objetos. Cuando la aplicación está en ejecución, y sólo entonces, se produce el enlace (dinámico) con los objetos contenidos en la librería.

La creación de librerías dinámicas corre a cargo del enlazador o montador (en nuestro caso el ld) aunque también es posible indicar al compilador las opciones necesarias para el montaje y de ese modo, será él quien se encargue de pasárselas al montador.

Cuando se crea un objeto dinámico es necesario que dicho código objeto sea independiente de la posición, para conseguir este tipo de código debe especificarse al compilador la opción -fPIC (Position IndependentCode). Dicho flag debe indicarse tanto en la compilación como en el montaje de la librería.

Para montar los objetos es necesario además indicar la opción -shared para que el resultado sea un fichero objeto ‘compartible’.

5.2.-USO DE COMPONENTES (VISUALES Y NO VISUALES) PROPORCIONADOS POR EL LENGUAJE

Un componente desde el punto de vista de programación está compuesto por varias secciones y el conjunto de todas ellas dan lugar a la creación de dicho componente.

Por tanto, primero para no perder el norte, vamos a empezar definiendo el convenio que es utilizado para organizar dichas secciones por TinyOs. En general, un componente posee tres grandes secciones que son: Configuration, Implementation, Module. Estas tres secciones han de estar obligatoriamente presentes en cualquier componente aunque puedan estar vacías.

El estándar de T i n y O s determina, que las secciones de Configuration e Implementatión han de ir en un fichero que recibirá el nombre del componente con la extensión .nc y la tercera sección de Module deberá de ir en otro fichero aparte que recibirá el nombre del componente concatenado con un M mayúscula (la M da el significado al fichero, es el significado de Module) , este último fichero también poseer áa extensión .nc.

Otra buena costumbre consiste en crear un fichero de header o cabecera con extensión .h que contenga todas las enumeraciones, registros o tipos de datos creados por el usuario de los que

Page 13: Unidad IV Acceso a Datos

hace uso la aplicación, y cuando se realiza esto la forma de ligar dicho fichero con los otros dos es utilizando al principio de los otros fichero la directiva include sheader; aunque como mención especial decir que si nos fijamos mejor en este directiva se puede ver que no se incorpora la extensión .h en la misma.

Ahora que ya sabes cuales son las secciones que va a contener cada fichero vamos a empezar a explicar cada una de ellas.

Implementatión. Esta sección se va a encargar de definir las conexiones que hay entre los diferentes componentes que utiliza la aplicación, esto es debido a que si recordamos un poco, se ha comentado que la programación de un componente (que se llevará a cabo en la sección de module) se hace utilizando interfaces y dichas interfaces para poder utilizar las que ha de proporcionar un componente, entonces básicamente es esta sección se definen cuáles son los componentes que proporcionan las interfaces a nuestra aplicación (por lo general serán componentes primitivos).

Una vez que conocemos la finalidad de esta sección y llegados a este punto, vamos a insertar un concepto nuevo que es la diferencia que existe entre una aplicación que está ya disponible para ser ejecutada en un sensor y un componente cualquiera. La diferencia es muy poca, y consiste en que una aplicación es un componente como cualquier cosa en este lenguaje que en su sección de implementación hace uso de un componente especial denominado Main.

5.3.- CREACIÓN Y USO DE PAQUETES/LIBRERIAS DEFINIDAS POR EL USUARIO

Los paquetes son grupos de clases relacionadas; ayudan a organizar su código y proporcionan otra capa encapsulamiento.

En programación, los paquetes, con frecuencia son útiles para agrupar las piezas relacionadas de un programa.

Un paquete sirve para dos propósitos: primero, suministra un mecanismo por el cual piezas relacionadas de un programa pueden ser organizadas como una unidad. Se debe tener acceso a las clases definidas dentro de un paquete a través de su nombre de paquete. Así, un paquete proporciona la manera de nombrar una colección de clases.

Segundo, un paquete participa en los mecanismos de control de acceso en java. Las clases definidas dentro de un paquete pueden hacerse privadas a ese paquete y no accesibles por código fuera del paquete. De este modo, el paquete suministra un medio por el cual las clases pueden ser encapsuladas.

Page 14: Unidad IV Acceso a Datos

DEFINIR UN PAQUETE:

Todas las clases en Java pertenecen a algún paquete. Como se mencionó anteriormente, cuando no se especifica la declaración package se usa el paquete predeterminado (o global). Además, el paquete predeterminado no tiene nombre, lo que lo hace transparente.

Aunque el paquete predeterminado es válido para programas de prueba cortos, es inadecuado para aplicaciones reales.

Para crear un paquete, coloque un comando package en la parte superior del archivo fuente de java.

Las clases declaradas dentro de ese archivo pertenecerán al paquete especificado. Puesto que un paquete define un espacio de nombre, los nombres de las clases que coloque dentro del archivo se convierten en parte de ese espacio del nombre del paquete.

La siguiente es la forma general de la declaración package:

packagepkg;

Aquí, pkg es el nombre del paquete. Por ejemplo, el siguiente enunciado crea un paquete de nombre Project1.

package Project1;

Java usa el sistema de archivo para manejar los paquetes con cada paquete almacenado en su propio directorio. Por ejemplo, los archivos .class para las clases que usted declare sean partes de Project1 debe guardarse en un directorio llamado Project1.

5.4 CONCEPTO DE HILO

El multihilo soportado en Java gira alrededor del concepto de hilo. La cuestión es, ¿qué es un hilo? De forma sencilla, un hilo es un único flujo de ejecución dentro de un proceso. Pero será mejor comenzar desde el principio y explicar qué es un proceso.Un proceso es un programa ejecutándose dentro de su propio espacio de direcciones. Java es un sistema multiproceso, esto significa que soporta varios procesos corriendo a la vez dentro de sus propios espacios de direcciones. Estamos más familiarizados con el término multitarea, el cual describe un escenario muy similar al multiproceso. Por ejemplo, consideremos la cantidad de aplicaciones que corren a la vez dentro de un mismo entorno gráfico. Mientras escribo esto, está corriendo Microsoft Word además de Internet Explorer, Windows Explorer, CD Player y elVolumen Control. Estas aplicaciones son todos procesos ejecutados dentro de Windows 95. De esta forma, se puede pensar que los procesos son análogos a las aplicaciones o a programas

Page 15: Unidad IV Acceso a Datos

aislados, pero cada proceso tiene asignado espacio propio de ejecución dentro del sistema. Un hilo es una secuencia de código en ejecución dentro del contexto de un proceso. Los hilos no pueden ejecutarse ellos solos; requieren la supervisión de un proceso padre para correr.Dentro de cada proceso hay varios hilos ejecutándose. Por ejemplo, Word puede tener un hilo en background chequeando automáticamente la gramática de lo que estoy escribiendo, mientras otro hilo puede estar salvando automáticamente los cambios del documento en el que estoy trabajando. Como Word, cada aplicación (proceso) puede correr varios hilos los cuales están realizando diferentes tareas. Esto significa que los hilos están siempre asociados con un proceso en particular.Los hilos a menudo son conocidos o llamados procesos ligeros. Un hilo, en efecto, es muy similar a un proceso pero con la diferencia de que un hilo siempre corre dentro del contexto de otro programa. Por el contrario, los procesos mantienen su propio espacio de direcciones y entorno de operaciones. Los hilos dependen de un programa padre en lo que se refiere a recursos de ejecución. La siguiente figura muestra le relación entre hilos y procesos.

5.5.-CREACION Y CONTROL DE HILOS

En Java, los hilos comparten el mismo espacio de memoria. Incluso comparten gran parte del entorno de ejecución, de modo que la creación de nuevos hilos es mucho más rápida que la creación de nuevos procesos. La ventaja que proporcionan los hilos es la capacidad de tener más de un camino de ejecución en un mismo programa. Así, con un único proceso, ejecutándose una JVM (Java Virtual Machine), habrá siempre más de un hilo, cada uno con su propio camino de ejecución.

En cuanto al proceso de creación de hilos, son dos los mecanismos que nos permiten llevarlo a cabo en Java: implementando la interfaz Runnable, o extendiendo la clase Thread, esto es,

Page 16: Unidad IV Acceso a Datos

creando una subclase de esta clase. Lo más habitual es crear hilos implementando la interfaz Runnable, dado que las interfaces representan una forma de encapsulamiento del trabajo que una clase debe realizar.

Así, se utilizan para el diseño de requisitos comunes a todas las clases que se tiene previsto implementar. La interfaz define el trabajo, la funcionalidad que debe cubrirse, mientras que la clase o clases que implementan la interfaz realizan dicho trabajo (cumplen esa funcionalidad).Todas las clases o grupos de clases que implementen una cierta interfaz deberán seguir las mismas reglas de funcionamiento.El otro mecanismo de creación de hilos, como ya hemos dicho, consistiría en la creación previa de una subclase de la clase Thread, la cual podríamos instanciar después.Por ejemplo,

class MiThread extends Thread {public void run() {

. . .}}

se corresponde con la declaración de un clase, MiThread, que extiende la clase Thread, sobrecargando el método Thread.run heredado con su propia implementación.

Arranque de un hiloEn el contexto de las aplicaciones, sabemos que es main la primera función que se invoca trasarrancar, y por tanto, lógicamente, es el lugar más apropiado para crear y arrancar otros hilos.La línea de código:t1 = new TestTh( "Thread 1",(int)(Math.random()*2000) );siendo TestTh una subclase de la clase Thread (o una clase que implemente la interfazRunnable) crea un nuevo hilo. Los dos argumentos pasados, sin mayor relevancia, satisfaránel prototipo del constructor de la clase y se utilizarán para la inicialización del objeto.Al tener control directo sobre los hilos, tenemos que arrancarlos explícitamente. Como ya secomentó anteriormente, es la función miembro start la que nos permite hacerlo. En nuestroejemplo sería:t1.start();start, en realidad es un método oculto en el hilo que llama al método run.

5.6.-SINCRONIZACION DE HILOS

Cuando dos o más hilos necesitan acceder de manera simultánea a un recurso de datos compartido necesitan asegurarse de que sólo uno de ellos accede al mismo cada vez. Java proporciona un soporte único, el monitor, es un objeto que se utiliza como cerrojo exclusivo. Solo uno de los hilos puede ser el propietario de un monitor en un instante dado. Los restantes hilos que estuviesen intentando acceder al monitor bloqueado quedan en suspenso hasta que el hilo propietario salga del monitor.

Page 17: Unidad IV Acceso a Datos

Todos los objetos de Java disponen de un monitor propio implícitamente asociado a ellos. La manera de acceder a un objeto monitor es llamando a un método marcado con la palabra clave synchronized. Durante todo el tiempo en que un hilo permanezca en un método sincronizado, los demás hilos que intenten llamar a un método sincronizado sobre la misma instancia tendrán que esperar. Para salir del monitor y permitir el control del objeto al siguiente hilo en espera, el propietario del monitor sólo tiene que volver del método

La sentencia synchronized

Si se utiliza una clase que no fue diseñada para accesos multihilo y, por ello, dispone de métodos no sincronizados que manipulan el estado interno, puede envolver la llamada al método en un bloque sincronizado. El formato general de la sentencia sincronizada es el siguiente:

synchronized(objeto) sentencia;

En el ejemplo, objeto es cualquier referencia al objeto, y sentencia suele ser un bloque que incluye una llamada al método de objeto, que solo tendrá lugar una vez que el hilo haya entrado con éxito en el monitor de objeto. Ahora veremos las formas de sincronización con un ejemplo:

class Callme {void call (String msg) { * también podía haber puesto synchronized antes de void *

System.out.print("[" + msg);try Thread.sleep(1000); catch (Exception e);System.out.println("]");

}}class caller implements Runnable {

String msg; Callme target; public caller(Callme t, String s) {

target = t;msg = s;new Thread(this).start();

} public void run() {

synchronized(target) {target.call(msg);

} }}class Synch { public static void main(String args[]) {

Callme target = new Callme();new caller(target, "Hola");new caller(target, "Mundo");new caller(target, "Sincronizado");

}}

Page 18: Unidad IV Acceso a Datos

Este programa imprime por pantalla el literal "Hola Mundo Sincronizado", cada palabra en una línea y entre comillas, se crea una instancia de Callme y tres instancias de caller que cada una de ellas referencia al mismo Callme con lo que necesitamos de una sincronización para el acceso a Callme, pues sino se mezclarían las tres llamada al haber una sentencia sleep que retrasa la ejecución de Callme dando lugar a que antes de que acabe un proceso deje libre el acceso a dicho objeto.