BAEL-3855
Updated
This commit is contained in:
		
							parent
							
								
									79be75cd74
								
							
						
					
					
						commit
						636e76ade0
					
				| @ -1,13 +1,9 @@ | |||||||
| package com.baeldung.concurrent.lock; | package main.java.com.baeldung.concurrent.lock; | ||||||
| import java.util.HashMap; |  | ||||||
| import java.util.Map; |  | ||||||
| import java.util.concurrent.ConcurrentHashMap; |  | ||||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||||
| 
 | 
 | ||||||
| import org.openjdk.jmh.annotations.Benchmark; | import org.openjdk.jmh.annotations.Benchmark; | ||||||
| import org.openjdk.jmh.annotations.BenchmarkMode; | import org.openjdk.jmh.annotations.BenchmarkMode; | ||||||
| import org.openjdk.jmh.annotations.Fork; | import org.openjdk.jmh.annotations.Fork; | ||||||
| import org.openjdk.jmh.annotations.Measurement; |  | ||||||
| import org.openjdk.jmh.annotations.Mode; | import org.openjdk.jmh.annotations.Mode; | ||||||
| import org.openjdk.jmh.annotations.OutputTimeUnit; | import org.openjdk.jmh.annotations.OutputTimeUnit; | ||||||
| import org.openjdk.jmh.annotations.Param; | import org.openjdk.jmh.annotations.Param; | ||||||
| @ -17,45 +13,36 @@ import org.openjdk.jmh.annotations.State; | |||||||
| import org.openjdk.jmh.annotations.Warmup; | import org.openjdk.jmh.annotations.Warmup; | ||||||
| 
 | 
 | ||||||
| @State(Scope.Thread) | @State(Scope.Thread) | ||||||
| @Fork(value = 2) | @Fork(value = 1) | ||||||
| @Warmup(iterations = 3) | @Warmup(iterations = 0) | ||||||
| public class BenchMark { | public class BenchMark { | ||||||
|     ConcurrentAccessMap accessMyMap; |     ConcurrentAccessMap accessMyMap; | ||||||
|  |     static final int SLOTS = 4; | ||||||
|  |     static final int THREADS = 1000; | ||||||
|  |     static final int BUCKETS = Runtime.getRuntime().availableProcessors() * SLOTS; | ||||||
|      |      | ||||||
|     @Param({"HashMap with Lock", "HashMap with Striped Lock",  |     @Param({"Single Lock", "Striped Lock"}) | ||||||
|       "ConcurrentHashMap with Lock", "ConcurrentHashMap with Striped Lock"}) |     private String lockType; | ||||||
|     private String type; |  | ||||||
| 
 | 
 | ||||||
|  |     @Param({"HashMap", "ConcurrentHashMap"}) | ||||||
|  |       private String mapType; | ||||||
|  |      | ||||||
|     @Setup |     @Setup | ||||||
|     public void setup() { |     public void setup() { | ||||||
|         switch (type) { |         switch (lockType) { | ||||||
|             case "HashMap with Lock": |             case "Single Lock": | ||||||
|                 accessMyMap = new CoarseGrained(getHashMap()); |                 accessMyMap = new SingleLock(); | ||||||
|                 break; |                 break; | ||||||
|             case "ConcurrentHashMap with Lock": |             case "Striped Lock": | ||||||
|                 accessMyMap = new CoarseGrained(getConcurrentHashMap()); |                 accessMyMap = new StripedLock(BUCKETS); | ||||||
|                 break; |  | ||||||
|             case "HashMap with Striped Lock": |  | ||||||
|                 accessMyMap = new LockStriped(getHashMap()); |  | ||||||
|                 break; |  | ||||||
|             case "ConcurrentHashMap with Striped Lock": |  | ||||||
|                 accessMyMap = new LockStriped(getConcurrentHashMap()); |  | ||||||
|                 break; |                 break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private Map<String, String> getHashMap() { |  | ||||||
|         return new HashMap<String,String>(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private Map<String, String> getConcurrentHashMap() { |  | ||||||
|         return new ConcurrentHashMap<String,String>(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Benchmark |     @Benchmark | ||||||
|     @BenchmarkMode(Mode.Throughput) |     @BenchmarkMode(Mode.Throughput) | ||||||
|     @OutputTimeUnit(TimeUnit.MILLISECONDS) |     @OutputTimeUnit(TimeUnit.MILLISECONDS) | ||||||
|     public void test() throws InterruptedException { |     public void test() throws InterruptedException { | ||||||
|         accessMyMap.doWork(type); |         accessMyMap.doWork(mapType, THREADS, SLOTS); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,33 +1,48 @@ | |||||||
| package com.baeldung.concurrent.lock; | package main.java.com.baeldung.concurrent.lock; | ||||||
| 
 | 
 | ||||||
|  | import java.util.HashMap; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.concurrent.CompletableFuture; | import java.util.concurrent.CompletableFuture; | ||||||
|  | import java.util.concurrent.ConcurrentHashMap; | ||||||
| 
 | 
 | ||||||
| import com.google.common.base.Supplier; | import com.google.common.base.Supplier; | ||||||
| 
 | 
 | ||||||
| public abstract class ConcurrentAccessMap { | public abstract class ConcurrentAccessMap { | ||||||
|     static final int SLOTS = 4; |  | ||||||
|     static final int THREADS = 10000; |  | ||||||
|     static final int BUCKETS = Runtime.getRuntime().availableProcessors() * SLOTS; |  | ||||||
|     private CompletableFuture<?>[] requests; |  | ||||||
|     protected Map<String, String> map; |  | ||||||
|      |      | ||||||
|     public ConcurrentAccessMap(Map<String, String> map) { |     public ConcurrentAccessMap() { | ||||||
|         this.map = map; |     } | ||||||
|  |      | ||||||
|  |     private Map<String, String> getHashMap() { | ||||||
|  |         return new HashMap<String,String>(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public final void doWork(String type) { |     private Map<String, String> getConcurrentHashMap() { | ||||||
|         requests = new CompletableFuture<?>[THREADS * SLOTS]; |         return new ConcurrentHashMap<String,String>(); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     private Map<String,String> setup(String type) { | ||||||
|  |         switch (type) { | ||||||
|  |             case "HashMap": | ||||||
|  |                 return getHashMap(); | ||||||
|  |             case "ConcurrentHashMap": | ||||||
|  |                 return getConcurrentHashMap(); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|         for (int i = 0; i < THREADS; i++) { |     public final void doWork(String type, int threads, int slots) { | ||||||
|             requests[SLOTS * i + 0] = CompletableFuture.supplyAsync(putSupplier(i)); |          CompletableFuture<?>[] requests = new CompletableFuture<?>[threads * slots]; | ||||||
|             requests[SLOTS * i + 1] = CompletableFuture.supplyAsync(getSupplier(i)); |          Map<String,String> map = setup(type); | ||||||
|             requests[SLOTS * i + 2] = CompletableFuture.supplyAsync(getSupplier(i)); | 
 | ||||||
|             requests[SLOTS * i + 3] = CompletableFuture.supplyAsync(getSupplier(i)); 	 |         for (int i = 0; i < threads; i++) { | ||||||
| 		} |             requests[slots * i + 0] = CompletableFuture.supplyAsync(putSupplier(map, i)); | ||||||
|  |             requests[slots * i + 1] = CompletableFuture.supplyAsync(getSupplier(map, i)); | ||||||
|  |             requests[slots * i + 2] = CompletableFuture.supplyAsync(getSupplier(map, i)); | ||||||
|  |             requests[slots * i + 3] = CompletableFuture.supplyAsync(getSupplier(map, i));       | ||||||
|  |           } | ||||||
|         CompletableFuture.allOf(requests).join(); |         CompletableFuture.allOf(requests).join(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     protected abstract Supplier<?> putSupplier(int x); |     protected abstract Supplier<?> putSupplier(Map<String,String> map, int key); | ||||||
|     protected abstract Supplier<?> getSupplier(int x); |     protected abstract Supplier<?> getSupplier(Map<String,String> map, int key); | ||||||
| } | } | ||||||
| @ -0,0 +1,38 @@ | |||||||
|  | package main.java.com.baeldung.concurrent.lock; | ||||||
|  | 
 | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.concurrent.locks.ReentrantLock; | ||||||
|  | 
 | ||||||
|  | import com.google.common.base.Supplier; | ||||||
|  | 
 | ||||||
|  | public class SingleLock extends ConcurrentAccessMap { | ||||||
|  |     ReentrantLock lock; | ||||||
|  | 
 | ||||||
|  |     public SingleLock() { | ||||||
|  |         lock = new ReentrantLock(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected synchronized Supplier<?> putSupplier(Map<String,String> map, int key) { | ||||||
|  |         return (()-> { | ||||||
|  |             boolean done = false; | ||||||
|  |             while(!done) { | ||||||
|  |                 done = lock.tryLock(); | ||||||
|  |             } | ||||||
|  |             map.put("key" + key, "value" + key); | ||||||
|  |             lock.unlock(); | ||||||
|  |             return null; | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected synchronized Supplier<?> getSupplier(Map<String,String> map, int key) { | ||||||
|  |         return (()-> { | ||||||
|  |             boolean done = false; | ||||||
|  |             while(!done) { | ||||||
|  |                 done = lock.tryLock(); | ||||||
|  |             } | ||||||
|  |             map.get("key" + key); | ||||||
|  |             lock.unlock(); | ||||||
|  |             return null; | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,46 @@ | |||||||
|  | package main.java.com.baeldung.concurrent.lock; | ||||||
|  | 
 | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.concurrent.locks.Lock; | ||||||
|  | 
 | ||||||
|  | import com.google.common.base.Supplier; | ||||||
|  | import com.google.common.util.concurrent.Striped; | ||||||
|  | 
 | ||||||
|  | public class StripedLock extends ConcurrentAccessMap { | ||||||
|  |     Striped<Lock> lock; | ||||||
|  | 
 | ||||||
|  |     public StripedLock(int buckets) { | ||||||
|  |         lock = getStripedLock(buckets); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private Striped<Lock> getStripedLock(int buckets) { | ||||||
|  |         Striped<Lock> map = Striped.lock(buckets); | ||||||
|  |         return map; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected synchronized Supplier<?> putSupplier(Map<String,String> map, int key) { | ||||||
|  |         return (()-> { | ||||||
|  |             Lock currentLock = lock.get("key" + key); | ||||||
|  |             boolean done = false; | ||||||
|  |             while(!done) { | ||||||
|  |                 done = currentLock.tryLock(); | ||||||
|  |             } | ||||||
|  |             map.put("key" + key, "value" + key); | ||||||
|  |             currentLock.unlock(); | ||||||
|  |             return null; | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected synchronized Supplier<?> getSupplier(Map<String,String> map, int key) { | ||||||
|  |         return (()-> { | ||||||
|  |             Lock currentLock = lock.get("key" + key); | ||||||
|  |             boolean done = false; | ||||||
|  |             while(!done) { | ||||||
|  |                 done = currentLock.tryLock(); | ||||||
|  |             } | ||||||
|  |             map.get("key" + key); | ||||||
|  |             currentLock.unlock(); | ||||||
|  |             return null; | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user