Observability

Posted: miércoles, 27 de octubre de 2021 by Skuarch in
1



Una forma de detactar fallas o anomalias en nuestro software es monitoreando los eventos que ocurren, observability es un poco mas que eso, no es solo monitorear es saber por que ocurrio y como se comporta tu sistema. 

Algo sencillo de mostrar como ejemplo es lo siguiente:

Monitoring: what and when
Observability: why and how

Observability es una practica de recolectar, visualizar y exahustivamente analizar datos telemetricos, mientras que Monitoring es limitado a simplemente informar cuando una anomalia ocurre.

Existen varios patrones que podemos aplicar

  • Health check api
  • Distributed tracing
  • Application metrics
  • Audit logging
  • Exception tracing
  • Application logging



GUIA DE ESTUDIO JAVA

Posted: martes, 30 de marzo de 2021 by Skuarch in
0

JAVA
Memory management:

La maquina virtual crea el heap al iniciar y cuando el heap se llena el garbage collector es llamado para borrar los objetos que ya no son usados. El heap esta dividido en 2 partes, young space and old space, young memory tambien es conocida como nursery, ahi viven los nuevos objectos, esto es para evitar que el garbage collector limpie nuevos objetos, despues de un cierto tiempo los objetos que estan en nursery pasan al old space, cuando el old space se llena el garbage es llamado y libera la memoria.

nursery -> objects with short live
old space -> remaing objects



Garbage collectors

Exiten mas de un garbage collectors (GC) en java que son usados para limpiar la memoria del programa donde estan corriendo, algunos de los algoritmos que se usan en el GC es mark and sweep y parallel compaction

Parallel compaction: Parallel compaction complements the existing parallel collector by performing full GCs in parallel to take advantage of multiprocessor (or multi-threaded) hardware.

Concurrent Mark Sweep (CMS): The concurrent mark sweep collector, also known as the concurrent collector or CMS, is targeted at applications that are sensitive to garbage collection pauses. It performs most garbage collection activity concurrently, i.e., while the application threads are running, to keep garbage collection-induced pauses short.


Programacion Orientada a Objectos:

Herencia:

En java la herencia es cuando una clase hijo extiende una clase padre y obtiene o hereda todos los metodos publicos y variables publicas que tenga la clase padre, existen varios tipos de herencia.

Herencia simple
Cuando una clase extiende de una padre.

Herencia Multiple
Cuando la clase padre extiende de otra clase, entonces la clase hijo tiene la herencia del padre y del abuelo.

Herencia Jerarquica
Es cuando multiples clases heredan de un solo padre, osea un padre con muchos hijos.

Encapsulamiento:
Es no mostrar al mundo exterior los datos de tu clase, o variables miembro, si alguien requiere saber un valor se debe de crear getters and setters.

Polimorfismo:
La palabra poliformisfo significa tener varias formas, en java el polimorfismo es cuando la clase puede tomar varias formas, utilizanto overloading and overriding es como se utiliza y se aplica el polimorfosmo en java.

Abstraccion
Crear una caja negra en donde solo lo relevante se muestre y lo que no sea importante no se muestre, es la forma aplicar la abstraccion en java es haciendo publicos los metodos que nececitan ser expuestos y los demas deben de ser privados que son los detalles de la implementacion.

Composition
Son relaciones entre objetos.
has-a o is-a, Person has a Job o Car is a Vehicle.
IS-A(Inheritance) and HAS-A (Association).

Data Types
En java los tipos de datos se dividen en 2, primitives y no primitives.
Primitives: short, byte, int, long, float, double, boolean and char
No Primitives: String, Array, Class y Object

Collections
Java collections es un framework que contiene interfaces, algoritmos, objectos.
Pueden ser usadas para store, retrive, manipulate and communicate agregated data.
Beneficios: Reduces programming effort, Increases program speed and quality.


Set — a collection that cannot contain duplicate elements
List — an ordered collection. Lists can contain duplicate elements
Queue — a collection used to hold multiple elements prior to processing, Queue provides additional insertion, extraction, and inspection operations
Queues typically, but do not necessarily, order elements in a FIFO (first-in, first-out) manner.
Deque — a collection used to hold multiple elements prior to processing.
Map — an object that maps keys to values.

Las siguientes interfaces son versiones ordenadas de set y map

SortedSet — a Set that maintains its elements in ascending order
SortedMap — a Map that maintains its mappings in ascending key order


As a rule, you should be thinking about the interfaces, not the implementations


HashTable: maps keys to values, any non-null object can be used as key or as value. la diferencia que tiene con el HashMap es que hashTable tiene initial capacity, que es The initial capacity controls a tradeoff between wasted space and the need for rehash operations, The load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased
Hashset: implement Set interface, backed by a Hash table, no garantiza que el orden se mantenga, permite nulls y no es sincronizada

ArrayDeque
ArrayList
TreeSet
LinkedHashSet

HashMap
LInkedHashMap
HasTable <-


Data structures
Es almacenar y organizar datos, se hicieron deprecated desde java 2
Enumeration, Bitset, Vector, Stack, Dictionary, HashTable and Properties.


Generics
Los genericos en java es especificar el tipo, por ejemplo cuando usamos una lista es posible indicar que la lista sea de String.

Comparator
Es una interface con un metodo compare que recibe dos objetos.

Comparable
Es una interface con un metodo compareTo que recibe solo un argumento

Class Loaders
Hay 3 principales class loaders en java.

Boostrap: carga las librerias del core de java (rt.jar)
Extention:carga las librerias jre/lib/ext
System: carga las librerias del classpath

Enums
Los enums en java son una clase especial y representa un grupo de constantes.

Volatile
Garantiza tener el mismo valor de una variable entre Threads.

Inmutable
Significa que el contenido no cambia, para hacer una clase inmutable se tiene evitar la herencia, los metodos deben de ser final, variables miembro deben de ser privados, los return deben de regresar nuevas instancias y no tener getters y setters.

Eager
Obtiene los datos inmediatamente.

Lazy
Obtiene los datos cuando son necesarios.

Serializacion
Es transformar el estado de un objeto en bytes.

Externalize
Es una interfas con readExternal y writeExternal.

Trasient
Evita la serializacion de una variable.

Tipos de Excepciones
Check Exception: se produce cuando el programa esta compilando.
Uncheck Exception: se produce cuando el programa esta corriendo

String
La clase String es inmutable lo que significa que no cambia, esta usa un pool para guardar los caracteres y asi maximizar la memoria evitando cadenas repetidas
Si se compara un string con otro string (==) este regresara un true por que comparamos el valor de las cadenas
Si la comparacion se realiza usando .equals() tambien regresara true, ejemplo:

String string1 = "hola";
String string2 = "hola";
if (string1.equals(string2)) {
System.out.println("iguales equals 1");
}

se imprimira "iguales equials 1"

comparando con == se evalua el valor de la cadena
if (string1 == string2) osea "hola" == "hola"
equals compara la referencia de memoria del objecto if (string1.equials(string2)) que en este caso son la misma por el pool de string que usa java
pero si se utiliza new String("hola") para crear cadenas y se compara con equal tambien regresara true, por que String es inmutable.
En la version de java 8+ es posible usar un switch con strings, antes de esta version no era posible usar strings en un switch.

StringBuffer vs StringBuilder
StringBuffer es sincronizada y StringBuilder no.
Si se desea concatenar una cadena con el simbolo "+" hay una probabilidad de que no se concatene, por que string es inmutable

String concat(String string) {
string = string + " hello";
}
Esto no modificara la cadena, al no crear un nuevo valor el string queda intacto.

Palindromos
Para saber si un string es un palindromo solo tenemos que revertir los caracteres, String class no tiene nada para revertir los caracteres de un string pero StringBuilder si lo tiene,

StringBuilder stringBuilder = new StringBuilder(string);
stringBuilder.reverse();
if (stringBuilder.toString().equals(anotherString))

Remplazar Caracteres
Para remplazar los caracteres de una cadena se puede usar replaceAll() de la clase String

char c = 'c';
str.replaceAll(Character.toString(c), "");

Predicate Interface usada en programacion functional comunmente para filtrar es posible utilizarlos con and operator.
Predicate p = String::isEmpty;

Stream
Clase para soportar programacion funcional, es la forma de usar las collectiones como flujos ejemplo: filter, sort, grouping.

Functional Interface
Es una interface que permite solo un methodo abstracto (default) es usada en functional programming.

Double Colon
Tambien conocido como method reference operator, es usado para llamar a un metodo por referencia:
stream.forEach(System.out::println);

Programacion Funcional
En Java una function puede ser algo como esto () -> el parentesis es para pasar argumentos y despues de la flecha se pone el cuerpo de la funcion
(a1, a2) -> System.out.println(a1);
Este es otro ejemplo de una funcion, es posible enviar una function como parametro, ejemplo:

public void receiveFunction(Function func)

Tambien es posible usar lambdas (funciones anonimas) ejemplo al crear un hilo:
new Thread(()-> someOtherMethod()).start();

Ejemplos de funciones en java:
BiFunction func = (x1, x2) -> x1 + x2;
Integer result = func.apply(5,6);

Function func2 = (input) -> "Result: " + String.valueOf(input);
String result = func2.appy(5);

Function: se usa para tener argumentos y un valor de regreso
BiFunction: acepta dos argumentos y tiene un regreso (return)
Consumers: aceptan argumentos y no regresan nada
Supplier: cuanto se tiene un tipo de retorno
Predicate: cuando se tiene argumentos y regresa un boolean

Existen mas tipos de funciones que se pueden checar en la documentacion oficial https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html

Lambdas
Una lambda es una function anonima por lo regular se utiliza con la clase stream que contienen las collections, ejemplo:
ArrayList list = new ArrayList<>();
list.stream().filter(x -> x>5);

Threads
ThreadLocal
Thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable.
son variables que se utilizan en los hilos y son independientes entre ellos; eso quiere decir que cada hilo tiene su propia copia independiente.

    private static final AtomicInteger nextId = new AtomicInteger(0);
        private static final ThreadLocal threadId =
        new ThreadLocal() {
            @Override protected Integer initialValue() {
                return nextId.getAndIncrement();
            }
        };

UncaughtExceptionHandler
Es una interface para obtener los errores en los hilos cuando una abrupta exception no manejada es disparada.

Join
Metodo para esperar hasta que el hilo muera; es posible enviar cuantos milisegundos tiene que esperar.
myThread.join(1000);

Futures
Se usa para programacion asincrona y puede tener un return, a diferencia de los hilos, con el metodo get obtienes el resultado y con cancel se puede cancelar la execucion.

Callable
A task that returns a result and may throw an exception.
Es una interface que tiene un metodo call muy similar a los hilos pero el callable puede tener un return

ExcecutionService
An Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks. An ExecutorService can be shut down, which will cause it to reject new tasks. Two different methods are provided for shutting down an ExecutorService. The shutdown() method will allow previously submitted tasks to execute before terminating, while the shutdownNow() method prevents waiting tasks from starting and attempts to stop currently executing tasks. Upon termination, an executor has no tasks actively executing, no tasks awaiting execution, and no new tasks can be submitted. An unused ExecutorService should be shut down to allow reclamation of its resources.

CountDownLatch
Cuando ejecutas mas de un hilo al mismo tiempo pero nececitas esperar hasta que todos los hilos terminen, countDownLatch es la forma de tener un contador dentro del hilo y cuando el contador llegue a 0 la ejecucion de todos los hilos a terminado. 

Exchanger
Es utilizado para intercambiar objectos entre hilos.

Lock
Es utilizado para blockear un recurso similar a syncroinizar, pero un poco mejorado, las principales diferencias son, un bloque sincronizado es completo, a lo que me refiero es no existe un metodo como exitSyncornization() para detener la sincronizacion, a diferencia de lock

Lock lock = new ReentrantLock();

lock.lock();
    //critical section
lock.unlock();

Atomic
Otra manera de evitar usar sincronizacion en variables es usar variables atomicas, el ejemplo ilustra mejor la explicacion:

private int c = 0;
public synchronized void increment() {
        c++;
}

Es equivalente a:

private AtomicInteger c = new AtomicInteger(0);
public void increment() {
        c.incrementAndGet();
}

LinkedList vs ArrayList
Para las tareas comunes es preferible usar ArrayList, para tareas de insercion y delete es preferible una lista ligada.
La lista ligada tiene una referencia hacia el siguiente nodo de la lista.

Tipos de tipado
dynamic typing: var i = 1; i = "hello"; // OK
weak typing: '1' + 2 = '12'; // OK
strong typing: 1 + '2' // ERROR
static typing: int i = 1; i = 'hello' //ERROR
static typing: int i = (int) 3.14 //ERROR

Reference copy
Este concepto es cuando quieres que dos variables tenga la misma referencia en memoria.

Object copy
Es tener dos objetos con los mismo valores pero diferente referencia en memoria.

Shallow copy
Es tener una referencia en memoria en medio de dos objectos




Observer
HashCode
Codigo LinkList

aws S3 Commands

Posted: sábado, 13 de julio de 2019 by Skuarch in
0


Estos son algunos de los comando para S3 que pueden ser útiles, para crear un bucket o vaciarlo
Subir archivos al bucket (el . significa desde este folder)
aws s3 sync . s3://nombre-bucket

Habilitar el bucket como website
aws s3 website s3://nombre-bucket/ --index-document index.html

Agregar un archivo de policy para dar permisos
aws s3api put-bucket-policy --bucket nombre-bucket --policy file://policy.json

Borrar el contenido del bucket
aws s3 rm s3://nombre-bucket --recursive

Ejemplo de archivo de policy.json

{
  "Version": "2008-10-17",
  "Statement": 
     [
       {
         "Sid": "AllowPublicRead",
         "Effect": "Allow",
         "Principal": {
           "AWS": "*"
         },
         "Action": "s3:GetObject",
         "Resource": "arn:aws:s3:::nombre-bucket/*"
       }
     ]
}

CONCEPTOS BASICO DE EXPRESIONES REGULARES

Posted: domingo, 23 de octubre de 2016 by Skuarch in Etiquetas: ,
0


Las expresiones regulares no son tan regulares como lo dice su nombre algunas cosas no estan soportadas en ciertos lenguajes, en esta entrada tratare de dar algunos ejemplos de expresiones regulares (regex) que se adaptan a la mayoria de los lenguajes, pero por favor checa con tu lenguaje si la expresion funciona igual debido a que no son un standar pueden varias entre lenguajes

^ inicio de linea
Cuando queremos buscar algo en nuestra cadena el signo ^ le indica a la expresion regular que lo que buscamos debe de estar al principio de la linea

$ fin de linea
Muy parecido al ejemplo anterios pero este indica que lo que buscamos debe de estar al final de la linea

podemos hacer una mezcla de esto por ejemplo buscar lineas vacias que seria algo como esto

^$
Eso nos regresara las lineas vacias

[ée] clases de caracteres
Con los corchetes indicamos que nos busque esos caracteres exactos, la expresion regular solo buscara la e y la e con acento

[A-Z] rangos
Los corchetes tambien sirven para establecer rangos, en este caso es un rango con letras mayusculas, la expresion solo buscara de la A a las Z en mayusculas

[a-z] rangos 
Es exactamente los mismo pero con minusculas

[A-Z][a-z] combinando rangos
Se pueden hacer combinaciones entre rangos, en este ejemplo se combinan las mayusculas y las minisculas

[^a-z] negacion
En este caso el caret o circumplejo se utiliza para negar, entonces la expresion buscara todo lo que no es minusculas

[A-z][^a-z] el primer caracter tiene que ser mayusculas y lo que le sigue tiene que ser negado a minusculas
La expresion que se encuentra arriba busca el primer caracter en mayusculas de la A-Z y despues cualquier cosa que no sea una minuscula de la a-z

[$] los corchetes hacen que no lo cuente como fin de linea

El signo de dolares es un caracter especial, pero si esta entre corchetes, la expresion regular no lo tomara encuenta y buscara un signo de dolares

| pipe 
El pipe se utiliza para hacer un OR

(gmail|yahoo) grupos
En la expresion anterior estamos usando pararentesis para crear grupos y lo combinamos con un pipe para que busque cualquiera de las dos cadenas que se encuentran en los parentesis

. cualquier caracter
El punto se utiliza para que la expresion busque en cualquier caracter

? opcional
El signo de interrogacion indica que el match es opcional

+ busca uno o mas veces
El signo de + buscara una o mas veces la cadena a buscar

{e} busqueda de caracteres
Con las llaves hacemos una busqueda que puede ser repedia y de un caracter en concreto

3{e} buscar el caracter
El ejemplo anterios buscara 3 veces el caracter "e"

[a-z]{3} busca tres minusculas 

El ejemplo anterior buscara tres minusculas en la cadena

\b[a-z]+@
Busca de la a-z y tiene un tope o frontera que es la arroba

Si deceamos un ejemplo para buscar etiquetas html esto puede ayudar

<.+> ejemplo para buscar etiquetas html
Las expresiones regulares son ambiciosas, eso quiere decir que buscaran todas las ocurrencias en la cadena, si queremos evitar eso se puede utilizar el ?

<.+?> esto hace una busqueda detenida

Para realizar la busqueda de numeros se puede utilizar la siguiente expresion

\d busca numeros

\d+(?= pesos) look a head
Busca los numeros y que tengas despues la palabra pesos

(?<=MXN )\d+ look behind
Lo contrario al anterior, MXN es la cadena a buscar, que puede ser cualquier otra

\W caracter alfanumerico
(?1) insensetive 
Estos son otros ejemplos de como crear grupos

(\W+)@(\W) grupos la arroba no es algo especial
Espero que esta pequeña introduccion de sirva de algo, si no es asi pues largate y buscale por otro lado


HABILITAR ACCESO REMOTO A DOCKER API

Posted: miércoles, 30 de marzo de 2016 by Skuarch in Etiquetas: , , , ,
0


Si deseas enviar comandos a la api de docker en ubuntu 14.04 tienes que realizar estos sencillos pasos
sudo sed -i -e 's/#DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4"/DOCKER_OPTS="-H tcp:\/\/127.0.0.1:2375 -H unix:\/\/\/var\/run\/docker.sock"/g' /etc/default/docker

reiniciar el servicio

sudo service docker restart

verificar que todo este correcto

curl -s http://127.0.0.1:2375/images/json

USAR JAVA Y JAVASCRIPT COMO SCRIPTING

Posted: jueves, 4 de junio de 2015 by Skuarch in Etiquetas: , , , , ,
0


Para poder usar java y javascript en un archivo .sh solo tienes que seguir estos sencillos pasos

crear un archivo con la extencion .sh

poner en la primeria linea el path donde se encuentra el ejecutable de nashorn

#!/usr/lib/jvm/jdk1.8.0_45/bin/jjs -fv

obviamente esta ruta puede cambiar pero no olvides essto "-fv"

ahora puedes usar java y javascript como scripting y este es un ejemplo completo


#!/usr/lib/jvm/jdk1.8.0_45/bin/jjs -fv
var Runnable = Java.type('java.lang.Runnable');
var Printer = Java.extend(Runnable, {
    run: function() {
        print('printed from a separate thread');      
    }
});
var Thread = Java.type('java.lang.Thread');
new Thread(new Printer()).start();
new Thread(function() {
    print('printed from another thread');
}).start();


Como te puedes dar cuenta aqui se esta usando los hilos de java dentro de javascript.
Para hacer esto asegurate que tienes la version 8 de java instalado.


espero te sirva y si no pues largate !!!

DETECTAR AMENAZAS AL INSTALAR APK'S EN ANDROID

Posted: jueves, 4 de septiembre de 2014 by Skuarch in Etiquetas: , , ,
0


En ocaciones nos encontramos en internet algunas aplicaciones (.apk) que deseamos instalar en nuestro android, pero como sabemos si estos archivos son seguros de instalar en nuestros dispositivos, pues me puse a investigar y a consultar google y encontre algunos sitios interesantes que acontinuacion les muestro

El que mas me sirvio fue este

http://apkscan.nviso.be/


solo arrastras tu .apk y sueltas, esperas un tiempo y te mostrara una pagina con los resultados

otro que es muy similar es este

http://scan.netqin.com/en/

basicamente es lo mismo

y por ultimo tenemos este

http://anubis.iseclab.org/?action=home

los tres hacen los mismo y algunos tienen la opcion de mandarte el resultado a tu correo.

Si el apk es de un tamaño pequeño puedes usar este servio y mandar tu apk por correo y recibir el resultado por el mismo

scan@virustotal.com

espero te sirva y si no, pues largate

CONSEJOS PARA PYTHON

Posted: sábado, 16 de agosto de 2014 by Skuarch in Etiquetas: , , ,
0


Python es un lenguaje con varios años y es muy maduro, aunque seria bueno que tengan algunas cosas como poder hacer un metodo privado y me refiero a que sea de en verdad privado y que cuente con un programador de tareas para realizar una tarea periodicamente, si tu no nececitas de estas cualidades python es un lenguaje ideal para ti.

Esta breve introduccion busca ser sencilla y practica y esta cenrada para equipos que estan basados en debian.

Todas las distribuciones linux tienen ya instalado python 2.+ asi es que para el desarrollo solo instalaremos algunos complementos para facilitarnos la vida

sudo apt-get install python-setuptools

Despues de instalar lo basico para python de te sugiero instalar estas dos utilidades

IPython y virtualenv

Y se instalan de esta forma sencilla

sudo apt-get install python-virtualenv ipython 

Ahora podras crear entornos virtuales y con ipython es una excelente shell para python con auto completado y colores, para crear un entorno virtual se realiza de esta forma

virtualenv env --no-site-packages

Eso creara un virtual enviroment con el nombre env y totalmente nuevo y se activa de esta manera

source env/bin/activate

Por ultimo si quieres saber que python esta corriendo en tu entorno puedes usar este simple comando

which python

Si quieres que un archivo .py se ejecute somo si fuera de bash agrega al principio del archivo esta linea

#!/usr/bin/env python

Como IDE te puedo recomendar ninja ide, es super sencilla intuitiva y ligera aqui esta su sitio oficial ninja ide


Por ultimo la palabra reservada self se puede comparar o parecer a la palabra this en otros lenguajes.

HERRAMIENTAS UTILIES PARA JAVA

Posted: miércoles, 16 de julio de 2014 by Skuarch in Etiquetas: , , , , ,
0


Siempre es bueno usar herramientas para checar la calidad de nuestro codigo, algunas de estas herramientas deben de ser impresindibles para todo desarrollador java

Eclipse Memory Analize
Este es un plug in de eclipse que nos ayuda a saber que puntos de nuetro programa pueden estar causando leaks, se nececita que configures la JVM para que trabaje correctamente

Proguard
El proposito general de proguard es ofuscar el codigo, como ya sabes decompilar el codigo en java es muy facil asi es que nunca esta de mas usar algun ofiscador, tambien tienen algunas otras cosas para mejorar el codigo


Dependometer

Analisis estatico o fisco de dependencias con dependometer, esta genial herramienta valida dependencias contra arquitecturas logicas estructurando esl sistema entro de clases, paquetes, subsistemas entre otras cosas.


DoctorJ

Es una aplication que analiza el codigo de java y la documentacion buscando errores comunes que javadoc no hace

MEJORAR EL PERFORMANCE DE JAVA

Posted: viernes, 11 de julio de 2014 by Skuarch in Etiquetas: , , ,
0


Siempres es bueno no gastar todos los recursos del procesador para poder correr mas aplicaciones, en este post voy a poner algunas de las mejores practicas para que tu codigo no influya tomando mas recursos de los que necesita, a claro que esta fue tomado de la guia de Glassfish oficial

Evitar serializacion y deserializacion

Serializacion y deszerializacion de objectos is proceso intensivo para el CPU y puede crear retrasos en tu aplicacion, Usa transient para reducir el monto de datos serializados

StringBuilder para concatenar Strings

Para mejorar el performance al menos al usar concatenacion de Strings, usa
StringBuilder.append();

Asignar null a las variables ya no se nececita

Esta practica ya no se nececita para ayudar al garbage collector identificando partes de memoria que pueden ser limpiadas

Declara metodos con final solo si es necesario

Modernos compiladores y otros procesos internos pueden hacer en linea  la optimizacion incluso si los metodos de java no son declarados como final

Solo usa final si tu estas absolutamente seguro de que el metodo no debe de ser sobreescrito.

Declara constantes como static y final

 El compilador dinamico puede hacer algunas optimizaciones facilmente cuando tu declaras constantes como static final

Evita Finalizers

Agregar finalizers al codigo hace que el garbage collector esa caro e impredecible, la maquina virtual no garantiza el tiempo que correran los finalizers; Finalizers no siempre son ejecutados antes de que el programa termine, evita usarlos para no crear una aplicacion impredecible.

Declarar los argumentos de un metodo como finales

Si estos no son modificados en el metodo, en general declara todas las variables final si no van a ser modificadas

Synchronize solo cuando sea necesario

Manten los bloques de sincronizacion lo mas corto posible y si es posible evita la sincronizacion.