Always consider flexibility-usability trade off in daily life and at work
as the flexibility of a system increases, its usability decreases
Wednesday, August 28, 2013
Wednesday, August 21, 2013
Sunday, August 18, 2013
Thursday, August 01, 2013
Daemon Threads in Java
A daemon thread is a thread, that does not prevent the JVM from exiting
when the program finishes but the thread is still running. An example
for a daemon thread is the garbage collection.
When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named
Threads in java are created as non daemon default, and the prolongs life time of application
Lets explain with examples
In example 1, process prints current time at each 1 sec period endlessly since thread of Timer is non deamon, and JVM waits for job completion of that thread.
In example 2, nothing is printed and process is terminated without waiting timer to do its job since Timer thread is created as daemon, see line 8.
In example 3, timer gets chance to execute during 10 seconds since main thread waits 10 sec (see line 19) and than process is terminated since main thread does its job after line 19 and thread of timer is a daemon thread which does not prevent JVM to terminate the process.
When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named
main of some designated class).Threads in java are created as non daemon default, and the prolongs life time of application
Lets explain with examples
Example 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package test; import java.util.Timer; import java.util.TimerTask; public class DeamonThreadTest { public static void main(String[] args) throws InterruptedException { Timer timer = new Timer(); timer.schedule(new TimerTask(){ @Override public void run() { System.out.println(System.currentTimeMillis()); } }, 1000, 1000); } } |
In example 1, process prints current time at each 1 sec period endlessly since thread of Timer is non deamon, and JVM waits for job completion of that thread.
Example 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package test; import java.util.Timer; import java.util.TimerTask; public class DeamonThreadTest { public static void main(String[] args) throws InterruptedException { Timer timer = new Timer(true); timer.schedule(new TimerTask(){ @Override public void run() { System.out.println(System.currentTimeMillis()); } }, 1000, 1000); } } |
In example 2, nothing is printed and process is terminated without waiting timer to do its job since Timer thread is created as daemon, see line 8.
Example 3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package test; import java.util.Timer; import java.util.TimerTask; public class DeamonThreadTest { public static void main(String[] args) throws InterruptedException { Timer timer = new Timer(true); timer.schedule(new TimerTask(){ @Override public void run() { System.out.println(System.currentTimeMillis()); } }, 1000, 1000); Thread.sleep(10000); } } |
In example 3, timer gets chance to execute during 10 seconds since main thread waits 10 sec (see line 19) and than process is terminated since main thread does its job after line 19 and thread of timer is a daemon thread which does not prevent JVM to terminate the process.
Monday, May 20, 2013
Friday, May 17, 2013
Sunday, April 07, 2013
Java Memory Structure
There are two memory regions in the JVM: the heap and the stack. Local
variables and methods reside on the stack, everything else on the heap.
Additionally class definitions are hold in a part of heap called permanent generation.
This Java heap memory is structured again into regions, called generations. The longer an object lives, the higher the chance it will be promoted to an older generation. Young generations(such as Eden on Sun JVM) are more garbage collected than older generations(survivor and tenured on Sun JVM). However, there is also some separate heap space called permanent generation. Since it is a separate region, it is not considered part of the Java Heap space. Objects in this space are relatively permanent. Class definitions are stored here, as are static instances.
The OutOfMemoryError: PermGen Space error occurs when the permanent generation heap is full. Although this error can occur in normal circumstances, usually, this error is caused by a memory leak.
The first thing one can do is to make the size of the permanent generation heap space bigger.
This cannot be done with the usual –Xms(set initial heap size) and –Xmx(set maximum heap size) JVM arguments, since as mentioned, the permanent generation heap space is entirely separate from the regular Java Heap space, and these arguments set the space for this regular Java heap space. However, there are similar arguments which can be used(at least with the Sun/OpenJDK jvms) to make the size of the permanent generation heap bigger:
would set its maximum size to 256m, which is 4 times bigger than the default size.
Reference:
http://www.integratingstuff.com/2011/07/24/understanding-and-avoiding-the-java-permgen-space-error/
Additionally class definitions are hold in a part of heap called permanent generation.
This Java heap memory is structured again into regions, called generations. The longer an object lives, the higher the chance it will be promoted to an older generation. Young generations(such as Eden on Sun JVM) are more garbage collected than older generations(survivor and tenured on Sun JVM). However, there is also some separate heap space called permanent generation. Since it is a separate region, it is not considered part of the Java Heap space. Objects in this space are relatively permanent. Class definitions are stored here, as are static instances.
The OutOfMemoryError: PermGen Space error occurs when the permanent generation heap is full. Although this error can occur in normal circumstances, usually, this error is caused by a memory leak.
The first thing one can do is to make the size of the permanent generation heap space bigger.
This cannot be done with the usual –Xms(set initial heap size) and –Xmx(set maximum heap size) JVM arguments, since as mentioned, the permanent generation heap space is entirely separate from the regular Java Heap space, and these arguments set the space for this regular Java heap space. However, there are similar arguments which can be used(at least with the Sun/OpenJDK jvms) to make the size of the permanent generation heap bigger:
-XX:MaxPermSize=256m
would set its maximum size to 256m, which is 4 times bigger than the default size.
Reference:
http://www.integratingstuff.com/2011/07/24/understanding-and-avoiding-the-java-permgen-space-error/
Thursday, February 28, 2013
Creating Dynamic HTML form with JQuery
In following sample, we will generate form elements dynamically according to provided html snippet in text area. I do nothing, jquery does all job :), thanks to it.
When user enters html form elements in text area and submit "Add html code entered in text are to form" button, form elements will be generated dynamically.
When user clicks on "Submit" button, form elements will be sent with GET method to google :) :
https://www.google.com/?education=HighSchool&TofD=Day
Here is html code, you have to download jquery and put it next to this html file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <!doctype html> <html> <head> <meta charset="utf-8"> <title>Demo</title> </head> <body> <script src="jquery-1.9.1.js"></script> <script> $( document ).ready(function() { $("#add").click(function( event ){ $("#formdiv").html(""); htmlcode = document.getElementById("htmlcode").value; $("#formdiv").html(htmlcode); }); }); </script> <textarea rows="4" cols="50" id="htmlcode"></textarea> <br/> <input name="add" type="button" value="Add html code entered in text area to form" id="add"/> <br/> SUBMISSION FORM: <table border=1> <tr><td> <form method="get" action="http://www.google.com"> <div name="formdiv" id ="formdiv"></div> <input type="submit" value="Submit"/> </form> </td></tr> </table> </body> </html> |
Dynamic Java Code Execution at Runtime with BeanShell
BeanShell provides to execute code snippets at runtime without compiling and restarting JVM. This functionality enables us to execute custom operations at runtime. Lets consider following case: Admin user of our system wants to manipulate a system value at runtime and enters a configuration for that purpose. Lets say, parameter, which manipulation will be executed on, holds a string tokenized with pipe character and we wants to change its value by finding max part of tokenized values.
Here is how that operation can be implemented with pure java
Now lets see if this operation shall be done at runtime with provided code snippet:
As easy as much above. Here is output:
Finally, i must say that altough first execution takes some time, succeeding executions takes faily short time. BeanShell provides us significant flexibility over processes at runtime.
Here is how that operation can be implemented with pure java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package com.ferhat.beanshell.work; import java.util.StringTokenizer; public class ValueManipulatorByJava { public static String getMax(String input) { StringTokenizer tok = new StringTokenizer(input, "|"); int max = 0; while (tok.hasMoreElements()) { int intval = Integer.parseInt((String) tok.nextElement()); if (intval > max) { max = intval; } } return String.valueOf(max); } public static void main(String[] args){ long start = System.currentTimeMillis(); System.out.println("Result is :" + getMax("9|3|10|11|1|8")); System.out.println("Java evaluation took " + (System.currentTimeMillis() - start) + " msec"); } } |
Now lets see if this operation shall be done at runtime with provided code snippet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | package com.ferhat.beanshell.work; import bsh.EvalError; import bsh.Interpreter; public class ValueManipulatorByBeanShell { public static String getMax(String input, String script) throws EvalError { Interpreter i = new Interpreter(); i.set("input", input); Object output = i.eval(script); return (String) output; } public static void main(String[] args) throws EvalError { String script = "StringTokenizer tok = new StringTokenizer(input, \"|\");\n" + " int max = 0;\n" + " while (tok.hasMoreElements()) {\n" + " int intval = Integer.parseInt((String) tok.nextElement());\n" + " if (intval > max) {\n" + " max = intval;\n" + " }\n" + " }\n" + " return String.valueOf(max);\n" + ""; String input = "9|3|10|11|1|8"; long start = System.currentTimeMillis(); String output = getMax(input, script); System.out.println("Result is: " + output); System.out.println("BeanShell evaluation took " + (System.currentTimeMillis() - start) + " msec"); start = System.currentTimeMillis(); output = getMax(input, script); System.out.println("Result is: " + output); System.out.println("BeanShell evaluation took " + (System.currentTimeMillis() - start) + " msec"); start = System.currentTimeMillis(); output = getMax(input, script); System.out.println("Result is: " + output); System.out.println("BeanShell evaluation took " + (System.currentTimeMillis() - start) + " msec"); } } |
1 2 3 4 5 6 | Result is: 11 BeanShell evaluation took 69 msec Result is: 11 BeanShell evaluation took 8 msec Result is: 11 BeanShell evaluation took 8 msec |
Finally, i must say that altough first execution takes some time, succeeding executions takes faily short time. BeanShell provides us significant flexibility over processes at runtime.
Saturday, February 16, 2013
Dependency Inversion Principle (DIP)
This principle is D of S.O.L.I.D design principles.According to Dependency Inversion Principle,
Here is some more explanation on DIP with a good example.
- High-level modules should not depend on low-level modules. Both should depend on abstractions.
- Abstractions should not depend upon details. Details should depend upon abstractions. (See Reference)
Here is some more explanation on DIP with a good example.
Interface Segregation principle (ISP)
This principle is I of S.O.L.I.D design principles.
Interface Segregation Principle stats that a client should not implement an interface if it doesn’t use that. this happens mostly when one interface contains more than one functionality and client only need one functionality and not other.Interface design is tricky job because once you release your interface you can not change it without breaking all implementation. Another benefit of this desing principle in Java is, interface has disadvantage to implement all method before any class can use it so having single functionality means less method to implement.
Here is an easy to understand ISP example
Interface Segregation Principle stats that a client should not implement an interface if it doesn’t use that. this happens mostly when one interface contains more than one functionality and client only need one functionality and not other.Interface design is tricky job because once you release your interface you can not change it without breaking all implementation. Another benefit of this desing principle in Java is, interface has disadvantage to implement all method before any class can use it so having single functionality means less method to implement.
Here is an easy to understand ISP example
Open Closed Principle (OCP)
This principle is O of S.O.L.I.D design principles.
According to Open Closed Principle, Software entities (Classes, modules, functions) should be OPEN for EXTENSION, CLOSED for MODIFICATION.
Code above violates OCP principle, because if a new shape is required to be drawn, it needs change in Drawer so refactor code as below to be OCP compatible:
....
According to Open Closed Principle, Software entities (Classes, modules, functions) should be OPEN for EXTENSION, CLOSED for MODIFICATION.
Lets try to reflect on the above
statement- software entities once written shouldn’t be modified to add
new functionality, instead one has to extend the same to add new
functionality. In otherwords you don’t touch the existing modules
thereby not disturbing the existing functionality, instead you extend
the modules to implement the new requirement. So your code is less rigid
and fragile and also extensible. (See Reference)
Lets look at the code below which draws triangle and rectangle:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public class OCPViolation { class Drawer{ public void drawRectangle(Rectangle shape){ System.out.println("Rectangle is drawn"); } public void drawTriangle(Triangle shape){ System.out.println("Triangle is drawn"); } } class Rectangle{} class Triangle{} public static void main(String[] args) { OCPViolation test = new OCPViolation(); Drawer drawer = test.new Drawer(); Rectangle rect = test.new Rectangle(); Triangle tri = test.new Triangle(); drawer.drawRectangle(rect); drawer.drawTriangle(tri); } } |
Code above violates OCP principle, because if a new shape is required to be drawn, it needs change in Drawer so refactor code as below to be OCP compatible:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public class OCPCompatible { class Drawer { public void draw(Shape shape) { shape.draw(); } } interface Shape { public void draw(); } class Rectangle implements Shape { public void draw() { System.out.println("Rectangle is drawn"); } } class Triangle implements Shape { public void draw() { System.out.println("Triangle is drawn"); } } public static void main(String[] args) { OCPCompatible test = new OCPCompatible(); Drawer drawer = test.new Drawer(); Rectangle rect = test.new Rectangle(); Triangle tri = test.new Triangle(); drawer.draw(rect); drawer.draw(tri); } } |
Single-Responsibility Principle (SRP)
This principle is S of S.O.L.I.D design principles.
According to Single Responsibility Principle, Every class should have a single responsibility: It should have
a single purpose in the system, and there should be only one reason to change
it.
The SRP is one of the simplest of the principle , and one of the hardest to get right.
A detailed description with an example can be found here
Liskov Substitution Principle (LSP)
This principle is L of S.O.L.I.D design principles.
According to Liskov Substitution Principle, Subtypes must be substitutable for super type i.e. methods or functions which uses super class type must be able to work with object of sub class without any issue”. LSP is closely related to Single responsibility principle and Interface Segregation Principle. If a class has more functionality than subclass might not support some of the functionality and does violated LSP. In order to follow LSP design principle, derived class or sub class must enhance functionality not reducing it. (See Reference)
How can we identify LSP violation?
Derived class may require less functionalities than the Base class, so some methods would be redundant. We might be using IS-A to check for Super-Sub relationships, but LSP doesn’t use only IS-A, but it also requires that the Sub types must be substitutable for the Super class. And one cannot decide the substitutability of sub class in isolation. One has to consider how the clients of the class hierarchy are going to use it. (See Reference)
Lets take look at the code below which violates LSP by binding swim and fly functionality to Base class Bird and use this functionalities by sub classes.
When we run above code, boom!
So lets fix it by seperating responsibilities as SwimmableBird and FlyableBird:
.
According to Liskov Substitution Principle, Subtypes must be substitutable for super type i.e. methods or functions which uses super class type must be able to work with object of sub class without any issue”. LSP is closely related to Single responsibility principle and Interface Segregation Principle. If a class has more functionality than subclass might not support some of the functionality and does violated LSP. In order to follow LSP design principle, derived class or sub class must enhance functionality not reducing it. (See Reference)
How can we identify LSP violation?
Derived class may require less functionalities than the Base class, so some methods would be redundant. We might be using IS-A to check for Super-Sub relationships, but LSP doesn’t use only IS-A, but it also requires that the Sub types must be substitutable for the Super class. And one cannot decide the substitutability of sub class in isolation. One has to consider how the clients of the class hierarchy are going to use it. (See Reference)
Lets take look at the code below which violates LSP by binding swim and fly functionality to Base class Bird and use this functionalities by sub classes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | import java.util.ArrayList; import java.util.List; /* * This class demonstrates Liskov Substitution Principle */ public class LSPViolation { abstract class Bird{ public abstract String getName(); public void sound(){ System.out.println(getName() + " sounds"); } public void fly(){ System.out.println(getName() + " flies"); } public void swim(){ System.out.println(getName() + " swims"); } } class Canary extends Bird{ public void swim(){ throw new UnsupportedOperationException( "Canary can not swim"); } public String getName() { return "canary"; } } class Penguin extends Bird{ public String getName() { return "penguin"; } public void fly(){ throw new UnsupportedOperationException( "penguin can not fly"); } } public static void main(String[] args) { LSPViolation lspViolation = new LSPViolation(); List<Bird> birds = new ArrayList<Bird>(); birds.add(lspViolation.new Penguin()); birds.add(lspViolation.new Canary()); for (Bird bird : birds){ bird.sound(); bird.swim(); bird.fly(); } } } |
When we run above code, boom!
penguin sounds
penguin swims
Exception in thread "main" java.lang.UnsupportedOperationException: penguin can not fly
at LSPViolation$Penguin.fly(LSPViolation.java:40)
at LSPViolation.main(LSPViolation.java:54)
So lets fix it by seperating responsibilities as SwimmableBird and FlyableBird:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | /* * This class demonstrates Liskov Substitution Principle */ public class LSPCompatible { abstract class Bird{ public abstract String getName(); public void sound(){ System.out.println(getName() + " sounds"); } } abstract class FlyableBird extends Bird{ public void fly(){ System.out.println(getName() + " flies"); } } abstract class SwimmableBird extends Bird{ public void swim(){ System.out.println(getName() + " swims"); } } class Canary extends FlyableBird{ public String getName() { return "canary"; } } class Penguin extends Bird{ public String getName() { return "penguin"; } } } |
Friday, December 28, 2012
Construct Comma Seperated String from List
Ihtiyac bir cogumuzun muhakkak karsilastigi, bir liste'den icindeki elemanlari bir seperator ile ayiran string olustumak. Benim de yaptigim ve bir cok kod'da karsilastigim hic te hos olmayan bir yontem: Efendim liste null mudur, bos mudur, dolu mudur kontrolu, sonrasinda liste for dongusunde taranir, her bir item'in sonuna seperator eklenir, bir stringBuffer'a append edilir, son item'dan sonra virgul koymamak icin if check'i yapilir falan derken hic te yakisikli olmayan kod ortaya cikar.
Iyi de Apache Commons bunu bizim icin zaten en guzelinden yapiyor ki
Outputs:
Just for clean codings..
Iyi de Apache Commons bunu bizim icin zaten en guzelinden yapiyor ki
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
public class Gunaydin {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("ahmet");
list.add("mehmet");
list.add("mustafa");
List<String> list2 = null;
// Join all Strings in the Array into a Single String, separated by $#$
System.out.println(StringUtils.join(list, "$#$"));
}
}
Outputs:
ahmet$#$mehmet$#$mustafa
Just for clean codings..
Regular Expressions Reference Guide
Regular expressions really ease to much string operations and validations instead of applying legacy methodologies. Being comfortable in regular expressions depends just practicing :) whenever has a chance to apply. Below is a list of regular expresssion constructs referenced from tutorial on oracle. There are also some examples with really good explanations at mkyong.
Just for quality coding...
Usage of Pattern and Matcher :
java.util.regex.Pattern pattern = Pattern.compile(regex);
java.util.regex.Matcher matcher = pattern.matcher(searchString);
while (matcher.find()) {
System.out.println(String.format("I found the text"
+ " \"%s\" starting at "
+ "index %d and ending at index %d.%n",
matcher.group(), matcher.start(), matcher.end());
}
Just for quality coding...
Character Classes
| Construct | Description |
|---|---|
[abc] |
a, b, or c (simple class) |
[^abc] |
Any character except a, b, or c (negation) |
[a-zA-Z] |
a through z, or A through Z, inclusive (range) |
[a-d[m-p]] |
a through d, or m through p: [a-dm-p] (union) |
[a-z&&[def]] |
d, e, or f (intersection) |
[a-z&&[^bc]] |
a through z, except for b and c: [ad-z] (subtraction) |
[a-z&&[^m-p]] |
a through z, and not m through p: [a-lq-z] (subtraction) |
NegationTo match all characters except those listed, insert the "^" metacharacter at the beginning of the character class. This technique is known as negation.RangesTo specify a range, simply insert the "-" metacharacter between the first and last character to be matched, such as [1-5] or [a-h]UnionsYou can also use unions to create a single character class comprised of two or more separate character classes. To create a union, simply nest one class inside the other, such as[0-4[6-8]]. This particular union creates a single character class that matches the numbers 0, 1, 2, 3, 4, 6, 7, and 8.IntersectionsTo create a single character class matching only the characters common to all of its nested classes, use&&, as in [0-9&&[345]].
This particular intersection creates a single character class matching
only the numbers common to both character classes: 3, 4, and 5.SubtractionFinally, you can use subtraction to negate one or more nested character classes, such as[0-9&&[^345]]. This example creates a single character class that matches everything from 0 to 9, except the numbers 3, 4, and 5.Predefined Character Classes
Quantifiers
|
Boundary Matchers
| Boundary Construct | Description |
|---|---|
^ |
The beginning of a line |
$ |
The end of a line |
\b |
A word boundary |
\B |
A non-word boundary |
\A |
The beginning of the input |
\G |
The end of the previous match |
\Z |
The end of the input but for the final terminator, if any |
\z |
The end of the input |
Usage of Pattern and Matcher :
java.util.regex.Pattern pattern = Pattern.compile(regex);
java.util.regex.Matcher matcher = pattern.matcher(searchString);
while (matcher.find()) {
System.out.println(String.format("I found the text"
+ " \"%s\" starting at "
+ "index %d and ending at index %d.%n",
matcher.group(), matcher.start(), matcher.end());
}
Monday, November 12, 2012
Don’t reinvent the wheel
Use guava libraries for most of utility needs you face while developing.
"Guava project contains several of Google's core libraries that we rely on in our Java-based projects: collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, and so forth."
"Guava project contains several of Google's core libraries that we rely on in our Java-based projects: collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, and so forth."
Anti RDBMS
A good article about when and why to use NO-SQL storage systems : http://www.metabrew.com/article/anti-rdbms-a-list-of-distributed-key-value-stores
Check http://www.couchbase.com
Check http://www.couchbase.com
Sunday, October 14, 2012
Simple Producer Consumer With LinkedBlockingQueue
Here is a simple Producer/Consumer sample using java.util.concurrent.LinkedBlockingQueue. Simply, Cachiers process tasks waiting in dropbox produced by Producer.
Task class which is processed by Cachier:
Dropbox class is the box that tasks are dropped in. This class has LinkedBlockingQueue containing task objects to be processed with max size 20
Producer is responsible from producing tasks and putting them to DropBox. If dropbox reaches its limit, producer thread will be blocked till queue has empty slot
Cachier is consumer and responsible from processing tasks, it waits till dropbox has a task to be processed
Here is the main class starting application with 1 producer and 3 consumer
Task class which is processed by Cachier:
public class Task {
private int taskNumber;
public Task(int taskNumber) {
this.setTaskNumber(taskNumber);
}
public void setTaskNumber(int taskNumber) {
this.taskNumber = taskNumber;
}
public int getTaskNumber() {
return taskNumber;
}
}
Dropbox class is the box that tasks are dropped in. This class has LinkedBlockingQueue containing task objects to be processed with max size 20
import java.util.concurrent.LinkedBlockingQueue;
public class Dropbox {
LinkedBlockingQueue<Task> blockingQueue = new LinkedBlockingQueue<Task>(20);
public Task take() throws InterruptedException {
return blockingQueue.take();
}
public void put(Task t) throws InterruptedException {
blockingQueue.put(t);
}
}
Producer is responsible from producing tasks and putting them to DropBox. If dropbox reaches its limit, producer thread will be blocked till queue has empty slot
public class Producer implements Runnable {
private Dropbox d;
public Producer(Dropbox d) {
this.d = d;
}
@Override
public void run() {
int i = 0;
while (true) {
Task t = new Task(i++);
try {
d.put(t);
System.out.println(t.getTaskNumber() + " is added");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Cachier is consumer and responsible from processing tasks, it waits till dropbox has a task to be processed
public class Cashier implements Runnable {
private Dropbox d;
private String name;
public Cashier(Dropbox d, String name) {
this.d = d;
this.name = name;
}
@Override
public void run() {
while (true) {
try {
Task t = d.take();
System.out.println("Processing " + t.getTaskNumber() + " by "
+ name);
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
Here is the main class starting application with 1 producer and 3 consumer
public class Main {
public static void main(String[] args) {
Dropbox d = new Dropbox();
Producer p = new Producer(d);
Cashier c1 = new Cashier(d, "Ahmet");
Cashier c2 = new Cashier(d, "Mehmet");
Cashier c3 = new Cashier(d, "Fatih");
new Thread(c1).start();
new Thread(c2).start();
new Thread(c3).start();
new Thread(p).start();
}
}
Friday, October 12, 2012
Subscribe to:
Posts (Atom)


