,

Thursday 7 August 2014

Internal Working of HashSet

HashSet in java
HashSet implements Set interface.It is a collection that contains no duplicate elements. HashSet is unordered.
Let us undertsand Internal working of HashSet using the below example. The example contains Employee class with two members id and name. We are implementing the hashcode , equals and toString methods.

Demo 1:

import java.util.HashSet;

/**
 *
 * @author Ganesh.Rashinker
 *
 */
class Employee {
private int id;
private String name;

public Employee(int id, String name) {
super();
this.id = id;
this.name = name;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}

@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + "]";
}
}

public class MainClass {

public static void main(String[] args) {
HashSet<Employee> set = new HashSet<Employee>();
Employee emp1 = new Employee(1, "Jack");
Employee emp2 = new Employee(2, "Robert");
Employee emp3 = new Employee(2, "Nancy");
Employee emp4 = new Employee(2, "Tom");
set.add(emp1);
set.add(emp2);
set.add(emp3);
set.add(emp4);
System.out.println(set);
}

}
Output:
[Employee [id=2, name=Robert], Employee [id=1, name=Jack], Employee [id=2, name=Nancy], Employee [id=2, name=Tom]]

HashSet uses HashMap internally. The value added to set is added as a key to HashMap and the value is a dummy static object. the above output shows that the data is unordered. The add method of HashSet call the put  method of HashMap internally.








Conclusion: HashSet uses HashMap internally and so it is best practice to implement hashcode and equals for the class , whose object is added in HashSet.The element of set is stored as key and the static object(dummy Object) of Object class is stored as value of HashMap.

Tuesday 5 August 2014

ThreadPool in java

ThreadPool is used when you want to restrict the number of threads and execute all the tasks using those threads. It has better performance as specific number of threads are started once and they execute the task , once the tasks are completed other tasks are assigned and executed by the same thread. So instead of creating as many threads as Runnable , it is better to start a specific number of threads at one time and the execute all the tasks accordingly.
In the below program , tasks are added to LinkedList which are executed by the threads. The LinkedList is used to enqueue and deque the tasks.

Note: To keep the code simple , minimum functionality is added so that the Runnables are added and executed by the thread-pool

TestThreadPool is the class which has the main function. It instantiates the thread-pool with the number of threads. In the main function we are creating 10 tasks and adding these tasks to the thread-pool.

Demo 1:
//file TestThreadPool.java
package com.i;
/**
 * 
 * @author Ganesh.Rashinker
 * 
 */

// class with main function
public class TestThreadPool {

public static void main(String[] args) {

// starting the number of threads
MyThreadPool threadPool = new MyThreadPool(2);
// creating 10 tasks and adding in thread pool
for (int i = 1; i <= 10; i++) {
MyTask task = new MyTask(i);
threadPool.doTask(task);
}

// when task completed , two threads are still waiting
threadPool.join();
}
}

MyTask is a class which implements Runnable. These would be the tasks added and executed by the threadpool.
//file MyTask.java
package com.i;
/**
 * 
 * @author Ganesh.Rashinker
 * 
 */

public class MyTask implements Runnable {

private int taskNo;

public MyTask(int taskNo) {
super();
this.taskNo = taskNo;
}

@Override
public void run() {
System.out.println("started the task: " + taskNo);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ended the task: " + taskNo);
}
}

MyThreadPool is the basic threadpool implementation which takes care of starting the number of threads and executing all the tasks using these threads. MyWorkerThread is the worker thread of threadpool which does the task of executing the runnable tasks.
//file MyThreadPool.java
package com.i;
import java.util.LinkedList;
/**
 * 
 * @author Ganesh.Rashinker
 * 
 */

//ThreadPool class using ThreadGroup
public class MyThreadPool extends ThreadGroup {

private boolean isAlive;

private LinkedList<Runnable> queue;

public MyThreadPool(int numThreads) {
super("ThreadPool");
isAlive = true;
queue = new LinkedList<Runnable>();
for (int i = 0; i < numThreads; i++) {
// starting WorkerThreads
new MyWorkerThread().start();
}
}

// adding tasks
public synchronized void doTask(Runnable task) {
queue.add(task);
notify();
}

// returns/gives the task to WorkerThread
protected synchronized Runnable giveTask() {
while (queue.size() == 0) {
if (!isAlive) {
return null;
}
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return (Runnable) queue.removeFirst();
}

// join function to notify all waiting threads
public void join() {
synchronized (this) {
isAlive = false;
notifyAll();
}
Thread[] threads = new Thread[activeCount()];
int threadNo = enumerate(threads);
for (int i = 0; i < threadNo; i++) {

try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

// WorkerThread class
private class MyWorkerThread extends Thread {

public void run() {
while (!isInterrupted()) {
Runnable task = giveTask();
if (task == null) {
return;
}
// running/executing the task
task.run();
}
}
}
}

Conclusion: Using thread-pool is efficient as the specific number of threads are started once , which executes the tasks one after the other on the basis of their availability. This approach is better than creating individual threads for each Runnable.