Stubmatic 5 is live now
Stubmatic is a npm tool which runs from CLI and it can be used to mock or proxy HTTP(s) calls. It helps to create simulators/stub/mocks of HTTP(s)/REST/SOAP easily. You can create mocked dynamic response without any programming. I recently published it’s 5th version yesterday with following additional features;
- Robust: 97%+ code coverage. Many bugs are fixed. Code quality and structure is improved.
- Now you can map multiple HTTP methods to a single method (not in short notations)
- Short notations
- Now you can proxy selected requests to other servers/simulators. This feature open many possibilities.
- You can validate yaml, json from CLI for quick feedback. I’ll add the support to validate XML soon.
- 2 more file stratigies are added.
- You can debug HTTP requests from CLI
- Support of yarn for fast installation
- Now stubmatic can be started from nodejs code as well
You can visit the site for latest updates and tutorials.
Life is so Simple, Dont make it Complex
Every tear is a sign of brokenness Cutting Onions!,
Every silence is sign of lonliness Zero balance,
Every smile is sign of kindness Daily Brushing,
Every sms is sign of remembrance extra balance.
:
Life is so Simple
Don’t make it Complex with difficult Explanations ..
Dealing with FEAR
when the source of our fear is the news, there is a really simple solution
Just turn it off
Often the problem is serious, but the solution may be very simple
A patient walks into a psychiatrist’s office and says to the doctor:
“Whenever I’m laying down, I feel like there’s someone under my bed. When I look under the bed, I feel like someone’s on top of the bed. Under, over, under, over. I’m going crazy!”
“I have a 2 year treatment plan,” says the psychiatrist.
“Come three times a week and you’ll be cured from this problem,” he continues.
“How much will you charge for this treatment?” asks the patient.
“$70.00 per session,” replies the psychiatrist.
“Well, I’m going to think about it,” concludes the patient.
They bump into each other six months later.
“Why didn’t you come see me anymore?” asks the psychiatrist.
“At 70 bucks, three times a week, for 2 years, your sessions were going to be too expensive. So I met this guy at the bar and he cured me for $5.00,” says the patient.
“Oh really? How?”
The patient replies, “For $5.00, he cut the legs off my bed…”
Often the problem is serious, but the solution may be very simple!
StubbyDB : Introduction video tutorial
How fast and easy we can make simulators without programming knowledge but regular expression. Best for QAs for integration testing.
Fix for floating div
First refer CSS snippet given below which is about to be used while discussing this problem & solution.
div {border:#000 1px solid; width: 50px;} .L {float:left;} .R {float:right;}
Let’s start.
Case 1
< div class="L">1< / div > < div >Amit Gupta< / div > < div class="R">2< / div > < div >articlestack.wordpress.com< / div >
Result :
Explanation:
First Div will let its upcoming elements take place in its right ie div containing “Amit Gupta” word. This is the basic property of a floated div. But a simple DIV never let any upcoming element take place to its right or left. So the 3rd div is shifted to next line. Similar to First DIV, Third DIV will also let its upcoming element place it’s left.
Doubt : Why 4th DIV is not starting from starting of line?
SubCase 1
<div> Container <div> child </div> </div>
Output
Container
SubCase 2
<div> Container <div class="L"> child </div> </div>
Output
Container
Explanation:
Height of a simple DIV with default width 100% is increased by the height of its element. On the opposite side, Height of floated DIV may increased and can pop out from its container on y-axis. So it doesn’t let any other element draw on y-axis.
Revised case 1
<div class="L" style="width: 150px">1</div> <div>Amit Gupta</div> <div class="R">2</div> <div>articlestack.wordpress.com</div>
Output:
Solution:
Use of clear property removes floating effect and let other element flow in normal way. For example;
<div class="L">1</div> <div>Amit Gupta</div> <div style="clear: left"></div> <div class="R">2</div> <div>articlestack.wordpress.com</div>
Output
Now if you increase the height of floated DIV it doesn’t affect upcoming elements.
<div class="L" style="width: 150px">1</div> <div>Amit Gupta</div> <div style="clear: left"></div> <div class="R">2</div> <div>articlestack.wordpress.com</div>
Output:
Warning:
For Browser’s compatibility
- Never use clear property with DIV using for displaying contents like
- Try to use clear:both instead of clear:left or clear:right.
Serialization – a Sci Fi story
Short story about serialization
After hard work of many years, Earth’s scientist developed a robot who can help them in daily work. But this robot was less featured than the robots which were developed by the scientist of Mars planet.
After a meeting between both planet’s scientist, it is decided that mars will send their robots to earth. But a problem occurred. The cost of sending 100 robots to earth was $100 millions. And it takes around 60 days for traveling.
Finally, Mar’s scientist decided to share their secret with Earth’s scientists. This secret was about the structure of class/robot. Earth’s scientists developed the same structure on earth itself. Mar’s scientists serialized the data of each robot and send it to earth. Earth’s scientists deserialized the data and fed it into each robot accordingly.
This process saved the time in communicating mass amount of data.
Some of the robots were being used in some defensive work on Mars. So their scientists marked some crucial properties of those robots as transient before sending their data to Earth. Note that transient property is set to null(in case of reference) or to default value(in case of primitive type) when the object gets deserialized.
One more point which was noticed by Earth’s scientists is that Mars’s scientists ask them to create some static variables to keep environmental detail. This detail is used by some robots. But Mars’s scientists dint share this detail since the environment on earth was different than Mars environment.
Even though knowing about the robot class structure and having serialized data Earth’s scientist were not able to deserialize the data which can make robots working.
Exception in thread "main" java.io.InvalidClassException: SerializeMe; local class incompatible: stream classdesc :
Mars’s scientists were waiting for the complete payment. Once the payment was done Mars’s scientists shared the serialVersionUID with Earth’s scientists. Earth’s scientist set it to robot class and everything became fine.
One of the Mar’s Scientist: Earth’s scientists are very slow to deserialize some of our best Robots. They must be using old version of java. They should either switch to new java version or to implement Externalizable.
Terms highlighted in above example are:
- Serialization
- Deserialization
- Transient variables
- Static variables
- Externalizable
Technically
Serialization is nothing but storing current state of an object to physical file. So the data can be used later by deserializing it.
When it is required:
- When a system gets crashed.
- When a player want to save all played game data so he can continue playing later.
- When a process need to be stopped by some reason. But it must continue working the next time with the same data.
How to
a. Implements Serializable or Externalizable
b. Serialize:
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("fileName")); out.writeObject(obj);
c. Deserialize:
ObjectInputStream in = new ObjectInputStream(new FileInputStream("fileName")); in.readObject();
1. Object of class A can’t be deserialized to the object of class B.
2. Object of class A can’t be deserialized to the object of class A itself if any of the instance variable changes its nature. For example
- Name
- Data type
- Removed from the class
- Make it transient or static
But if serialVersionUID is added to the class of serialized and deserialized object with same value then deserialization will not generate any error (excluding point b). So if variable is not found then its value is not set.
In short, deserialization finds instance variable with the same name they were used to serialize. If variable name is changed or they are removed from the class then it throws error. But if serialVersionUID is same then it skips initialization for not found variables.
In addition, if a variable is found with the same name but its datatype is changed then it generate error of casting even if serialVersionUID is same.
Changing their access level doesn’t impact.
3. If serialVersionUID is not same for the class of serialized and deserialized object then deserialization throws error even if class structure are exact same.
4. Methods, transient variables and static variables are not transient.
5. An object can be serialized only if its class implements either Serializable or Externalizable.
6. If extra variables found than the variables which are serialized then they are set to their default value at the time deserialization.
7. Making a class part of inheritance tree is allowed. But moving a class in existing inheritance tree up/down is not allowed since it can affect saved/serialized object tree.
Why Externalizable
- It provides control of reading/writing object to/from an output/input stream.
- It was very useful till Java 1.2 since reflection was slow
- You can decide which object has to left from object tree or what default value has to be set to transient variables while deserialization.
Methods of Externalizable
public void writeExternal(ObjectOutput out) throws IOException { out.writeFloat(x); out.writeFloat(y); out.writeFloat(z); out.writeFloat(w); } public void readExternal(ObjectInput in) throws IOException { x = in.readFloat(); y = in.readFloat(); z = in.readFloat(); w = in.readFloat(); }
Sample Code
I am attaching source code, I practiced on, for serialization and externalization.
Thread Tracer
This program can be integrated with your any java program to trace various states of a thread. It can help you to understand the flow of a thread. But remember, Tracer runs a thread to trace states of a thread. Tracer will not able to print all states of a thread. since there might be a situation when Tracer thread get served to CPU very late or with big interval and another thread changes its 3-4 states in between. I generally run Tracer 2-3 times for proper understanding.
I took its help to find out deadlock in my one of the program over nested monitor.
import java.lang.management.ManagementFactory; import java.lang.management.ThreadMXBean; import java.sql.Timestamp; import java.util.ArrayList; public class Tracer { private ArrayList <WrapperThread> threadList; Tracer() { threadList = new ArrayList < WrapperThread > (); } public void add(Thread t) { threadList.add(new WrapperThread(t)); } static { new Thread(() -> { System.out.println("Monitoring Deadlocks"); while (Thread.activeCount() >= 2) deadLockMonitor(); }, "DeadLock Monitor").start(); } private static void deadLockMonitor() { ThreadMXBean mx = ManagementFactory.getThreadMXBean(); long[] DevilThreads = mx.findDeadlockedThreads(); if (DevilThreads != null && DevilThreads.length > 0) { System.out.println(currentTime() + " :: Deadlock detected"); for (int i = 0; i < DevilThreads.length; i++) { System.out.println("Thread id :" + DevilThreads[i]); } System.out.println("Exiting from system"); System.exit(0); } } public void trace() { new Thread(() -> { while (Thread.activeCount() >= 2) { if (isStateChanged()) System.out.println (currentTime() + " :: "+threadList); } }, "Tracer").start(); } private boolean isStateChanged(){ for (WrapperThread wT : threadList) { if(wT.isStateChanged()) return true; } return false; } public static String currentTime() { return (new Timestamp(System.currentTimeMillis())).toString(); } }
Wrapper Thread
import java.lang.Thread.State; public class WrapperThread{ private String name; protected Thread originalThread; private State lastState; public WrapperThread(Thread t) { originalThread = t; name = t.getName(); lastState = originalThread.getState(); System.out.println(Tracer.currentTime() + " :: " + this); } public boolean isStateChanged() { State state = originalThread.getState(); if(lastState != state){ lastState = state; return true; } return false; } public State currentState() { return originalThread.getState(); } @Override public String toString() { return name+":"+currentState(); } }
How to use it in your program
Tracer t = new Tracer(); t.add(A); t.add(B); t.trace();
Happy coding 🙂
CyclicBarrier
CyclicBarrier = Cycle + Barrier
CyclicBarrier just force threads to wait until their count reached to N. Then release them to run on a wide road. And force next N threads to wait. and so on.
public class CycleBarrierDemo implements Runnable { CyclicBarrier controller; CycleBarrierDemo() { controller = new CyclicBarrier(1); } @Override public void run() { try { Thread.sleep(100); System.out.println(controller.getNumberWaiting()); System.out.println(Thread.currentThread().getName() + " has been arrived"); controller.await(); System.out.println(Thread.currentThread().getName() + " has been Passed"); } catch (Exception bbx) { System.out.println(bbx.getMessage()); } } public static void main(String[] argc) { CycleBarrierDemo cd = new CycleBarrierDemo(); Thread A = new Thread(cd, "A"); Thread B = new Thread(cd, "B"); Thread C = new Thread(cd, "C"); Thread D = new Thread(cd, "D"); A.start(); B.start(); C.start(); D.start(); } }
Output: [When barrier size was 1]
0
A has been arrived
A has been Passed
0
B has been arrived
B has been Passed
0
C has been arrived
C has been Passed
0
D has been arrived
D has been Passed
Output:[When barrier size was 2]
A has been arrived
1
B has been arrived
A has been Passed
B has been Passed
0
C has been arrived
1
D has been arrived
C has been Passed
D has been Passed
Java Multithreading – Final program
I code this program to explain Condition in java. Further I extended it to explain the use of
- Executor & ExecutorServices to make ThreadPool.
- Use of Future Object & Callable interface to enquiry/communicate with running thread.
- Use of Semaphore to control number of threads.
- Lock over synchronized block
- Threads inside threads
- Enum & EnumMap to store well known values.
- Condition (labelled wait & notify) to notify thread waiting for specific condition.
Condition
condition (since Java 5) is nothing but labeled wait(), notify() & notifyAll(). Let’s understand it with an example;
There are 2 containers: ChocoPowederContainer, WheatPowderContainer. CookieMaker takes some amount of powder from both containers to make a ChocoWheatCookie. There is a Filler who checks container with regular interval. If he finds any container empty, he fills it.
Condition:
- CookieMaker starts N threads say maker1, maker2,.. makerN to produce cookies.
- maker5, maker6, and maker9 found ChocoPowederContainer empty. They took powder from WheatPowderContainer.
- maker13, maker10, and maker7 found WheatPowderContainer empty. They took powder from ChocoPowederContainer.
- Filler finds ChocoPowederContainer empty. So he filled it and notifyAll() makers. After sometime Filler finds another container empty and fills it and notifyAll() again.
But maker13, maker10, and maker7 want to be notified only when WheatPowderContainer get filled. And maker5, maker6, and maker9 want to be notified only when ChocoPowederContainer get filled.
For the solution, Filler can make 2 Condition objects, say ChocoPowederContainerEmpty and WheatPowderContainerEmpty. maker5, maker6, and maker9 will call ChocoPowederContainerEmpty.await() and maker13, maker10, and maker7 will call WheatPowderContainer.await().
Filler will call WheatPowderContainerEmpty.signalAll() once WheatPowderContainer is filled. And so on.
Final Code
Cookie class: First I developed this code with this class then I omitted it. Because this class does nothing but getting/setting an EnumMap. So I directly moved this EnumMap into CookieMaker class
public class Cookie { EnumMap < Ingredient, Integer > ingredients; Cookie() { ingredients = new EnumMap < Ingredient, Integer > (Ingredient.class); } public void setIngredient(Ingredient i, int quantity) { ingredients.put(i, quantity); } public EnumMap < Ingredient, Integer > getIngredients() { return ingredients; } }
IngredientContainer Class – represents a container with some method to fill & consume container ingredient. As per the problem, a maker thread should wait if container is empty. If thread A waits for container 1 and B waits for container 2 and Filler fills container 1 then only thread A should be notified. So I have attached Condition object with container class itself.
public class IngredientContainer { private int capacity; //How much quantity of an ingredient a container can have private int quantityHeld; Condition empty; IngredientContainer(int c) { capacity = c; } //getters public int getQuantityRequired() { return capacity - quantityHeld; } public void fill(int n) throws Exception { if ((n + quantityHeld) > capacity) { throw new Exception("Overfilled"); } quantityHeld += n; } public boolean isEmpty() { return quantityHeld == 0; } /** * * @param n filled units * @return */ public int fillSafe(int n) { int require = capacity - quantityHeld; int toBeFilled = Math.min(require, n); quantityHeld += toBeFilled; return toBeFilled; } public void setEmptyCondition(Condition c) { this.empty = c; } public boolean getIngredient(int n) throws Exception { if (n > capacity) { throw new Exception("Accessing quantity more than capacity"); } if (quantityHeld >= n) { TimeUnit.SECONDS.sleep(1); quantityHeld -= n; return true; } System.out.println("Less Quantity Held"); return false; } }
Filler class – One filler is associated with one maker in our program who keeps watch on containers of associated maker only. And fills them.
import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; /* * Filler checks a Container with regular interval. Either it fills Container * safely or check it before filling it. * * @author Amit Gupta */ public class Filler { private ArrayList < IngredientContainer > ingredientContainers; int capacity = 6; private int checkInterval = 3; private int fillingQuantity = 2; private boolean isInterrupted = false; private Lock containerLock; public Filler(int c, Lock l) { ingredientContainers = new ArrayList < IngredientContainer > (); capacity = c; containerLock = l; } public void addContainer(IngredientContainer c) throws Exception { if (ingredientContainers.size() == capacity) throw new Exception("Filler is overloaded"); ingredientContainers.add(c); } /** * Filler checks container with regular interval and fills if it is empty. * @author Amit Gupta */ public void startFilling() { new Thread(new Runnable() { @Override public void run() { System.out.println("Filler has started working"); while (!isInterrupted) { try { TimeUnit.SECONDS.sleep(checkInterval); System.out.println("Filler starts checking containers"); containerLock.lock(); Iterator <IngredientContainer> itr = ingredientContainers.iterator(); while (itr.hasNext()) { IngredientContainer ingredientContainer = itr.next(); System.out.println("Require : " + ingredientContainer.getQuantityRequired()); System.out.println("Capacity : " + ingredientContainer.getCapacity()); System.out.println("Filling : " + fillingQuantity); int filledQ = ingredientContainer.fillSafe(fillingQuantity); //Try to fill required quantity only. System.out.println("Filled " + filledQ); ingredientContainer.empty.signalAll(); //This condition must be instantiate from CookieMaker } containerLock.unlock(); } catch (Exception e) { System.out.println(e.getMessage()); } } } }).start(); } public void stopFilling() { isInterrupted = true; } /** * How long Filler should wait checking a container. * @param checkInterval Seconds. default is 3 seconds. */ public void setCheckInterval(int checkInterval) { this.checkInterval = checkInterval; } /** * How much quantity should be filled in a container, if it is empty. * @param fillingQuantity default 10. */ public void setFillingQuantity(int fillingQuantity) { this.fillingQuantity = fillingQuantity; } }
CookieMaker class – This is heart of the program. All other classes are created to support this class. It seems little bit complex. So we’ll understand it into parts.
import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /* * CookieMaker bakes N cookies at a time. He can bake 1 type of cookie only * Required containers must be installed in prior to bake a cookie. * * @author Amit Gupta * */ public class CookieMaker implements Runnable { EnumMap < Ingredient, IngredientContainer > containers; int containerCapacity = 0; //How many containers a maker can have Semaphore bakingCapacity; //How many cookies a maker can bake EnumMap < Ingredient, Integer > cookie; private Lock bakingLock = new ReentrantLock(); private Lock containerLock = new ReentrantLock(); Filler fillingWorker = new Filler(6, containerLock); public void addContainer(Ingredient i, IngredientContainer c) throws Exception { //System.out.println("Adding " + i.toString() + " container."); if (containers.size() == containerCapacity) { throw new Exception("Containers over loaded"); } c.setEmptyCondition(containerLock.newCondition()); //System.out.println("Condition is added to Container"); fillingWorker.addContainer(c); //System.out.println("Container is added to Filler"); containers.put(i, c); System.out.println(i.toString() + "container added"); } public void StartBaking() { try { System.out.println(bakingCapacity.getQueueLength() + " are waiting"); bakingCapacity.acquire(); System.out.println(bakingCapacity.availablePermits() + " more threads can enter"); bakingLock.lock(); System.out.println(Thread.currentThread().getName() + " :: Entered."); Set < Ingredient > ingredients = cookie.keySet(); Iterator < Ingredient > itr = ingredients.iterator(); ExecutorService pool; Set < Future < Boolean >> tasks = new HashSet < Future < Boolean >> (); try { pool = Executors.newFixedThreadPool(containers.size()); while (itr.hasNext()) { System.out.println(); final Ingredient ingredient = itr.next(); tasks.add(pool.submit(new Callable < Boolean > () {@ Override public Boolean call() throws Exception { return getIngredient(ingredient); } })); } Iterator < Future < Boolean >> fuItr = tasks.iterator(); boolean tasksCompleted = true; while (fuItr.hasNext()) { Future < Boolean > f = fuItr.next(); tasksCompleted &= f.get(); } if (tasksCompleted) { System.out.println("Mixture is ready. Backing cookie"); pool.shutdown(); } } catch (Exception e) { e.printStackTrace(); } System.out.println("Thread " + Thread.currentThread().getName() + " :: completed"); bakingLock.unlock(); bakingCapacity.release(); //let other threads start baking fillingWorker.stopFilling(); } catch (InterruptedException ie) { ie.printStackTrace(); } } /** * Take ingredients from a container. Wait if container is empty. * @param ingredient * @return * @throws Exception * @throws InterruptedException */ private boolean getIngredient(final Ingredient ingredient) throws InterruptedException, Exception { containerLock.lock(); System.out.println("sub thread for " + ingredient.toString()); IngredientContainer container = containers.get(ingredient); System.out.println(ingredient.toString() + " Container has " + container.getQuantityHeld()); int quantity = cookie.get(ingredient); System.out.println("sub thread : Quantity require:" + quantity); while (!container.getIngredient(quantity)) { container.empty.await(); } //In real world I believe, this method will take some time to take ingredients from a container. TimeUnit.SECONDS.sleep(1); System.out.println("subThread " + ingredient.toString() + " has completed"); containerLock.unlock(); return true; } public static void main(String[] args) { IngredientContainer chocoPowderContainer = new IngredientContainer(12); IngredientContainer wheatPowderContainer = new IngredientContainer(15); CookieMaker cm = new CookieMaker(4, 5); EnumMap < Ingredient, Integer > chocoWheatBar = new EnumMap < Ingredient, Integer > (Ingredient.class); chocoWheatBar.put(Ingredient.ChokoPowder, 3); chocoWheatBar.put(Ingredient.WheatPowder, 1); try { cm.addContainer(Ingredient.ChokoPowder, chocoPowderContainer); cm.addContainer(Ingredient.WheatPowder, wheatPowderContainer); cm.setCookie(chocoWheatBar); } catch (Exception e) { System.out.println(e.getMessage()); } new Thread(cm, "maker1").start(); new Thread(cm, "maker2").start(); new Thread(cm, "maker3").start(); new Thread(cm, "maker4").start(); new Thread(cm, "maker5").start(); new Thread(cm, "maker6").start(); cm.fillingWorker.startFilling(); } @Override public void run() { if (checkSetup()) { StartBaking(); } else { System.out.println("Initial setup is required"); } } public CookieMaker() { containers = new EnumMap < Ingredient, IngredientContainer > (Ingredient.class); } public CookieMaker(int bc) { bakingCapacity = new Semaphore(bc); containers = new EnumMap < Ingredient, IngredientContainer > (Ingredient.class); } public CookieMaker(int bc, int cc) { bakingCapacity = new Semaphore(bc); this.containerCapacity = cc; containers = new EnumMap < Ingredient, IngredientContainer > (Ingredient.class); } public void setCookie(EnumMap < Ingredient, Integer > cookie) { this.cookie = cookie; } public void setBakingCapacity(int bakingCapacity) { this.bakingCapacity = new Semaphore(bakingCapacity); } public void setContainerCapacity(int containerCapacity) { this.containerCapacity = containerCapacity; } /** * Checks Maker's initial set up. * @throws Exception */ public boolean checkSetup() { boolean signal = false; /*if(bakingCapacity. < 1){ System.out.println("Maker can not bake cookies"); } else*/ if (containerCapacity < 1) { System.out.println("Container capacity is 0"); } else if (containers.size() < 1) { System.out.println("No container is installed."); } else { signal = true; } return signal; } }
I am not attaching output of above classes here since it is too long. I am chunking it and explaining you important parts.
bakingCapacity – Maker has the capacity of baking 4 cookies at a time. bakingCapacity semaphore keeps counting on running thread. If 4 threads are running and 1 completes its working, bakingCapacity allows 1 more thread. Review the output below;
0 are waiting
3 more threads can enter
maker1 :: Entered.
0 are waiting
2 more threads can enter
0 are waiting
1 more threads can enter
0 are waiting
0 more threads can enter
Thread maker1 :: completed
maker3 :: Entered.
0 more threads can enter
:
In above output, bakingCapacity allows 1st 4 threads to get entered. marker1 enters into its critical session. Total 4 threads are inside semaphore this time. Out of them 1 is running and other 3 are waiting. marker1 completes its work and get out from semaphore. marker3 enters into monitor. Now 2 threads are waiting and 1 is running. Total 3 threads are in semaphore. So bakingCapacity allows 1 more thread to get enter. And so on.
bakingLock: This lock ensures that only 1 thread can enter in its monitor. If you see in output you’ll notice following sequence;
maker1 :: Entered.
Thread maker1 :: completed
maker3 :: Entered.
Thread maker3 :: completed
maker5 :: Entered.
Thread maker5 :: completed
maker2 :: Entered.
Thread maker2 :: completed
maker4 :: Entered.
Thread maker4 :: completed
maker6 :: Entered.
Thread maker6 :: completed
Here the question arises if all threads are running in sequence then what is the need of multi-threading?
MultiThreadig is required when multiple tasks run parallel. And Locking is required when you fear that some other thread can change value of a variable required by current thread.
Let’s traverse each statement of StartBaking().
What type of ingredients a cookie has?
For each ingredient take required quantity from relevant container.
If 1 container is empty then take ingredient from another container and for 1st container to get filled.
Once ingredients are taken from all containers, bake cookie.
Ingredients are always fixed for a cookie type. It could be critical if a maker can produce multiple types of cookies. Moreover, local variables are always thread safe. So we need not to worry for point a).
For point b) & c), we will have to take ingredients from containers parallel. So for each container we’ll have to create one sub-thread. Containers are being filled by Filler. When a sub-thread takes ingredients from container, container’s quantity get reduced. So there is a critical condition when 2 threads check container quantity at the same time and both reduce it.
public boolean getIngredient(int n) throws Exception { : if (quantityHeld >= n) { quantityHeld -= n; return true; } : }
This section requires lock. Since we already acquiring lock in getIngredient() of Maker class. So there is no need of locking in StartBaking().
Once ingredients are taken, we don’t have to check any value which can be modified by any other thread.
containerLock – Condition discussed in above points proves the need of this lock. But we’ll analyze it.
java multithreading CookieMaker containers
Suppose marker1 creates 2 sub-threads A, B. marker2 creates C,D. All sub-threads call getIngredient() of Maker class. ChocoPowder Container has 2 units of powder while other container has 5 units. As per cookie recipe, A & C require 3 units while B & D require 1 unit.
A : enter
C: waiting
A: finds insufficient quantity in container. waits and releases lock.
C: enters
Filler : fills 2 units. So total units in ChocoPowder container are 4.
A & C both access getIngredient() of container class at the same time.
A & C both finds sufficient quantity. So both reduce quantity and come out.
Current quantity in ChocoPowder container is -2 units.
Where we require lock?
containerLock can be moved down since starting statements are creating local variables which are thread safe. Note that container is referencing field member. But its value is fixed so the next version of method could be as follows;
private boolean getIngredient(final Ingredient ingredient) throws Exception { IngredientContainer container = containers.get(ingredient); int quantity = cookie.get(ingredient); containerLock.lock(); while (!container.getIngredient(quantity)) { container.empty.await(); } containerLock.unlock(); return true; }
Even this move doesn’t solve the problem. Our need says that getIngredient() of container class should be accessed by only one thread at a time. So I must make it synchronized. I don’t require to synchronize fill() in our example.
This output will show that everything is fine after above changes.
A: sub thread for ChokoPowder
A: ChokoPowder Container has 0
A: sub thread : Quantity require:3
A: Less Quantity Held
B: sub thread for WheatPowder
B: WheatPowder Container has 0
B: sub thread : Quantity require:1
B: Less Quantity Held
C: sub thread for ChokoPowder
C: ChokoPowder Container has 0
C: sub thread : Quantity require:3
C: Less Quantity Held
D: sub thread for WheatPowder
D: WheatPowder Container has 0
D: sub thread : Quantity require:1
D: Less Quantity Held
Filler: Filler starts checking containers
Filler(choco): Require : 12
Filler(choco): Capacity : 12
Filler(choco): Filling : 2
Filler(choco): Filled 2
Filler(wheat): Require : 15
Filler(wheat): Capacity : 15
Filler(wheat): Filling : 2
Filler(wheat): Filled 2
A: Less Quantity Held
C: Less Quantity Held
B: subThread WheatPowder has completed
D: subThread WheatPowder has completed
Filler: Filler starts checking containers
Filler(choco): Require : 10
Filler(choco): Capacity : 12
Filler(choco): Filling : 2
Filler(choco): Filled 2
Filler(wheat): Require : 15
Filler(wheat): Capacity : 15
Filler(wheat): Filling : 2
Filler(wheat): Filled 2
A: subThread ChokoPowder has completed
C: Less Quantity Held
Mixture is ready. Backing cookie
Thread maker1 :: completed
Filler: Filler starts checking containers
Filler(choco): Require : 11
Filler(choco): Capacity : 12
Filler(choco): Filling : 2
Filler(choco): Filled 2
Filler(wheat): Require : 13
Filler(wheat): Capacity : 15
Filler(wheat): Filling : 2
Filler(wheat): Filled 2
subThread ChokoPowder has completed
Mixture is ready. Backing cookie
Thread maker2 :: completed
containerLock in Filler class : since we are creating only one thread of Filler class so there will not be another thread calling fillSafe() at the same time. Although writing it under lock is good practice. But some statements can be written out of lock as follows;
containerLock.lock(); int filledQ = ingredientContainer.fillSafe(fillingQuantity); ingredientContainer.empty.signalAll(); containerLock.unlock();
I hope this article can explain you more about multithreading. Keep reading …
Java Multithreading – External Locks
You must be aware with the need of synchronization after reading Bad synchronization leads program’s death and Synchronization – solve the mystery.
Well! synchronized has some limitations. Lets understand with this example.
public class DummyClass { private Integer age = 0; public void display(){ System.out.println(Thread.currentThread().getName() + ": " + age); } public void edit(int n){ age = n; } } public class SynchronizedLimitDemo { public static void main(String[] args) { final DummyClass dcObj = new DummyClass(); Thread amit = new Thread(new Runnable(){ @Override public void run() { try{ dcObj.edit(27); Thread.sleep(1000); dcObj.display(); }catch(InterruptedException ixp){ System.out.println(ixp.getMessage()); } } },"Amit Thread"); Thread arti = new Thread(new Runnable(){ @Override public void run() { try{ dcObj.edit(29); Thread.sleep(1000); dcObj.display(); }catch(InterruptedException ixp){ System.out.println(ixp.getMessage()); } } },"Arti Thread"); amit.start(); arti.start(); } }
In above stupid example, even if you synchronized display() & edit(), you can’t get proper output. Now see how external locking (since Java 5) can solve it.
public class DummyClass { private Integer age = 0; private Lock dataLock = new ReentrantLock(); public void display(){ System.out.println(Thread.currentThread().getName() + ": " + age); dataLock.unlock(); } public void edit(int n){ dataLock.lock(); age = n; } }
Output:
Arti Thread: 29
Amit Thread: 27
Warning: If a thread tries calling display() directly or before lock was acquired, it’ll generate run time exception. Similarly a thread can call edit() multiple times but can forget calling display(). It’ll lock the object forever.
This example is just to elaborate an advantage of Lock over synchronized.
Problem with synchronized keyword
- A synchronized block makes no guarantees about the sequence in which threads waiting to entering it are granted access.
- You cannot pass any parameters to the entry of a synchronized block. Thus, having a timeout trying to get access to a synchronized block is not possible.
- The synchronized block must be fully contained within a single method. It’s not possible that synchronization starts in one method and ends in another.
- If a thread meets synchronized block, where another thread already had entered into it, it is supposed to wait until another thread release the lock.
Java 5 provides another locking mechanism. Where
- A thread can request to acquire a lock with timeout period. If lock is not acquired then thread can do something else or can request again.
- A Lock can be started in one method and can end in another.
How to
synchronized
method( synchronized(this){ //critical section } }
Lock
Lock lock = new ReentrantLock(); method( lock.lock(); //critical section lock.unlock(); }
* It is good to call unlock() in finally block.
Methods
The Lock interface has the following primary methods:
- lock()
- lockInterruptibly()
- tryLock()
- tryLock(long timeout, TimeUnit timeUnit)
- unlock()
The lock() method locks the Lock instance if possible. If the Lock instance is already locked, the thread calling lock() is blocked until the Lock is unlocked.
The lockInterruptibly() method locks the Lock unless the thread calling the method has been interrupted. Additionally, if a thread is blocked waiting to lock the Lock via this method, and it is interrupted, it exits this method calls.
The tryLock() method attempts to lock the Lock instance immediately. It returns true if the locking succeeds, false if Lock is already locked. This method never blocks.
The tryLock(long timeout, TimeUnit timeUnit) works like the tryLock() method, except it waits up the given timeout before giving up trying to lock the Lock.
The unlock() method unlocks the Lock instance. Typically, a Lock implementation will only allow the thread that has locked the Lock to call this method. Other threads calling this method may result in an unchecked exception (RuntimeException).
Note:
If you have locked an object N times you will have to call unlock() N times.
Java Multithreading – join
Lets start with some example
method(){ Statement 1 Statement 2 }
If Statement 1 is a thread statement then Statement 2 can be executed any time. It doesn’t wait Statement 1 to be completed.
If Statement 1 is simple statement then Statement 2 can’t be executed until Statement 1 is completed.
If Statement 1 is a thread statement calling join() then Statement 2 can’t be executed until Statement 1 is completed.
If Statement 1 is a thread statement calling join(n) then Statement 2 can’t be executed until Statement 1 is completed or time n is over.
public class JoinDemo extends Object { public static Thread createThread(String name, long napTime) { final long sleepTime = napTime; Runnable r = new Runnable() { public void run() { try { print("in run() - entering"); Thread.sleep(sleepTime); } catch ( InterruptedException x ) { print("interrupted!"); } finally { print("in run() - leaving"); } } }; Thread t = new Thread(r, name); t.start(); return t; } private static void print(String msg) { String name = Thread.currentThread().getName(); System.out.println(name + ": " + msg); } public static void main(String[] args) throws Exception{ Thread[] t = new Thread[2]; t[0] = createThread("thread A", 2000); //t[0].join(); t[1] = createThread("thread B", 1000); } }
Explanation:
When createThread() get called it creates a thread. Thread.sleep() interrupts this thread. So another createThread() call takes place.
t[0] = createThread("thread A", 2000); //statement 1 t[1] = createThread("thread B", 1000); //statement 3
Output:
thread A: in run() – entering
thread B: in run() – entering
thread B: in run() – leaving
thread A: in run() – leaving
t[0] = createThread("thread A", 2000); //statement 1 t[0].join(); //statement 2 t[1] = createThread("thread B", 1000); //statement 3
Output
thread A: in run() – entering
thread A: in run() – leaving
thread B: in run() – entering
thread B: in run() – leaving
In above condition, first t[0] will be completed then statement 3 will be called.