how can i block the put method when cache reloading is being called.
Example: These are dummy classes not the actual.
Caching class
public class Class1 {
private static Map<Integer, Integer> map = new HashMap<>();
public Class1() {
for (int i = 0; i < 20; i++) {
map.put(i, ++i);
}
}
public void reload() throws InterruptedException {
Map<Integer, Integer> exist = map;
System.out.println("are you waiting ");
System.out.println("waiting over");
map = new HashMap<>();
for (Map.Entry<Integer, Integer> entry : exist.entrySet()) {
map.put(entry.getKey(), entry.getValue());
}
for (int i = 100; i < 120; i++) {
map.put(i, ++i);
}
}
public Map<Integer, Integer> getMap() {
return map;
}
}
Class initializing the cache
public class Class2 {
private static Class1 cache = new Class1();;
public Class1 getCache() {
return cache;
}
public void reload() throws InterruptedException {
cache.reload();
}
}
class using the cache
package com.diaryreaders.corejava.algorithms.dp;
public class Class3 {
public static void main(String[] args) {
final Class2 klass = new Class2();
Runnable runn1 = new Runnable() {
#Override
public void run() {
int i = 50, j = 50;
while (i < 100) {
System.out.println("I am stuck due to lock");
klass.getCache().getMap().put(i++, j++);
System.out.println(klass.getCache().getMap());
}
}
};
Runnable runn2 = new Runnable() {
#Override
public void run() {
try {
System.out.println("Calling reloading");
klass.reload();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t1 = new Thread(runn1);
Thread t2 = new Thread(runn2);
t1.start();
t2.start();
}
}
As thread t2 is calling reloading, t1 should be blocked i.e cache put method be blocked till reloading completes
Related
I'm trying to implement a producer-consumer model by using Hazelcast.
The producer puts an item to queue and the consumer consumes it using take() method.
I close the consumer application and start again. The consumer retrieves the previously consumed item from the queue.
I tried the Hazelcast Ringbuffer and I see the same behavior.
Is there a way to force to remove the consumed item from the queue in Hazelcast?
Thanks in advance
Producer.java:
public class Producer implements MembershipListener {
private HazelcastInstance hzInstance;
private Cluster cluster;
private IAtomicLong counter;
private IQueue<Data> dataQueue;
private IMap<String, List<Data>> dataByConsumerId;
public static void main(String[] args) {
Producer producer = new Producer();
Scanner scanIn = new Scanner(System.in);
while (true) {
String cmd = scanIn.nextLine();
if (cmd.equals("QUIT")) {
break;
} else if (cmd.equals("ADD")) {
long x = producer.counter.addAndGet(1);
producer.dataQueue.add(new Data(x, x + 1));
}
}
scanIn.close();
}
public Producer() {
hzInstance = Hazelcast.newHazelcastInstance(configuration());
counter = hzInstance.getCPSubsystem().getAtomicLong("COUNTER");
dataByConsumerId = hzInstance.getMap("CONSUMER_DATA");
dataQueue = hzInstance.getQueue("DATA_QUEUE");
cluster = hzInstance.getCluster();
cluster.addMembershipListener(this);
}
public Config configuration() {
Config config = new Config();
config.setInstanceName("hazelcast-instance");
MapConfig mapConfig = new MapConfig();
mapConfig.setName("configuration");
mapConfig.setTimeToLiveSeconds(-1);
config.addMapConfig(mapConfig);
return config;
}
#Override
public void memberAdded(MembershipEvent membershipEvent) {
}
#Override
public void memberRemoved(MembershipEvent membershipEvent) {
String removedConsumerId = membershipEvent.getMember().getUuid().toString();
List<Data> items = dataByConsumerId.remove(removedConsumerId);
if (items == null)
return;
items.forEach(item -> {
System.out.println("Push data to recover :" + item.toString());
dataQueue.add(item);
});
}
}
Consumer.java:
public class Consumer {
private String id;
private HazelcastInstance hzInstance;
private IMap<String, List<Data>> dataByConsumerId;
private IQueue<Data> dataQueue;
public Consumer() {
hzInstance = Hazelcast.newHazelcastInstance(configuration());
id = hzInstance.getLocalEndpoint().getUuid().toString();
dataByConsumerId = hzInstance.getMap("CONSUMER_DATA");
dataByConsumerId.put(id, new ArrayList<Data>());
dataQueue = hzInstance.getQueue("DATA_QUEUE");
}
public Config configuration() {
Config config = new Config();
config.setInstanceName("hazelcast-instance");
MapConfig mapConfig = new MapConfig();
mapConfig.setName("configuration");
mapConfig.setTimeToLiveSeconds(-1);
config.addMapConfig(mapConfig);
return config;
}
public static void main(String[] args) {
Consumer consumer = new Consumer();
try {
consumer.run();
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
private void run() {
while (true) {
System.out.println("Take queue item...");
try {
var item = dataQueue.take();
System.out.println("New item taken:" + item.toString());
var dataInCluster = dataByConsumerId.get(id);
dataInCluster.add(item);
dataByConsumerId.put(id, dataInCluster);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Data.java:
public class Data implements Serializable {
private static final long serialVersionUID = -975095628505008933L;
private long x, y;
public Data(long x, long y) {
super();
this.x = x;
this.y = y;
}
public long getX() {
return x;
}
public void setX(long x) {
this.x = x;
}
public long getY() {
return y;
}
public void setY(long y) {
this.y = y;
}
#Override
public String toString() {
return "Data [x=" + x + ", y=" + y + "]";
}
}
I have Counter class with 3 methods out of which 2 are synchronized, I want increment() to execute first and then the count(), so that count for each thread should always be 3000.
Instead of calling the count() from run() I can call it from within increment() is the only approach I can think of, Is there any other way to do So?
class Counter {
int count=0;
void print() {
System.out.println("Print called by: "+Thread.currentThread().getName());
}
synchronized void increment()
{
for(int i=1;i<=3000;i++)
count++;
}
synchronized void getCount() {
System.out.println(count);
count =0;
}
}
class MyThread1 extends Thread {
Counter c;
MyThread1(Counter c) {
this.c = c;
}
public void run() {
c.print();
c.increment();
c.getCount();
}
}
class MyThread2 extends Thread {
Counter c;
MyThread2(Counter c) {
this.c = c;
}
public void run() {
c.print();
c.increment();
c.getCount();
}
}
public class Demo {
public static void main(String args[]) {
Counter obj = new Counter();
MyThread1 t1 = new MyThread1(obj);
MyThread2 t2 = new MyThread2(obj);
t1.start();
t2.start();
}
}
Expected O/P in each case:
//The printing of "Print called by:" statement can be in any order as it's not synchronized but the count for each thread should always be 3000
Print called by: Thread-0
Print called by: Thread-1
3000
3000
Working example for my comment (You don't need MyThread1 and MyThread2):
public class Demo {
public static void main(String[] args) {
Counter obj = new Counter();
MyThread t1 = new MyThread(obj);
MyThread t2 = new MyThread(obj);
t1.start();
t2.start();
}
}
class Counter {
private final ThreadLocal<Integer> count = new ThreadLocal<Integer>() {
#Override
protected Integer initialValue() {
return 0;
}
};
void print() {
System.out.println("Print called by: " + Thread.currentThread().getName());
}
void increment() {
for (int i = 1; i <= 3000; i++)
count.set(count.get() + 1);
}
void getCount() {
System.out.println(count.get());
count.set(0);
}
}
class MyThread extends Thread {
Counter c;
MyThread(Counter c) {
this.c = c;
}
public void run() {
c.print();
c.increment();
c.getCount();
}
}
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo {
public static void main(String args[]) {
Counter obj = new Counter();
MyThread t1 = new MyThread(obj);
MyThread t2 = new MyThread(obj);
t1.start();
t2.start();
}
}
class Counter {
Lock lock = new ReentrantLock();
int count = 0;
void print() {
System.out.println("Print called by: " + Thread.currentThread().getName());
}
void increment() {
lock.lock();
for (int i = 1; i <= 3000; i++)
count++;
}
void getCount() {
System.out.println(count);
count = 0;
lock.unlock();
}
}
class MyThread extends Thread {
Counter c;
MyThread(Counter c) {
this.c = c;
}
public void run() {
c.print();
c.increment();
c.getCount();
}
}
You can use synchronized to block a thread.
here the example:
public void run() {
synchronized (Thread.class) {
c.print();
c.increment();
c.getCount();
}
}
synchronized needs an object as param, please use same object for both class MyThread1 and MyThread2
read https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html for more details.
Concurrent writing elements into the ConcurrentHashMap admits element. Requirements: writing must be done in different threads. Is there way to use advantages of the ConcurrentHashMap and do writing without blocking and sleeping?
Is there good code for iterator that accessed from different treads. Or is there other good variant to keep ieratian looking on the effectively-final requirement?
public class Task3v2 {
public static void main(String[] args) {
System.out.println("ConcurrentHashMap : "+timeIt(new ConcurrentHashMap<Integer, String>()));
}
static Iterator<Integer> integerIterator;
static {createIterator();}
private static void createIterator() {
integerIterator=
Stream.iterate(0, i -> i + 1).limit(100).collect(Collectors.toList()).iterator();
}
public static double timer(Runnable block) {
long start = System.nanoTime();
try {
block.run();
} finally {
long end = System.nanoTime();
return(end - start);
}
}
public static double timeIt(Map<Integer, String> map){
return timer(
()->{
new Thread(()->{
fillMap(map);
System.out.println("invoked");
readMap(map);
}).start();
});
}
private static void fillMap(Map<Integer, String> map){
int[] index = new int[1];
String[] tmp = new String[1];
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i = 0; i< 100; i++){
index[0] = i;
tmp[0] = "Name"+i;
new Thread(()->{
int a = integerIterator.next();
System.out.println("a :"+a);
map.put(a,"Name"+a);
}
).start();
}
}
private static void readMap(Map<Integer, String> map){
int[] index2 = new int[1];
for(int i = 0; i< 100; i++){
index2[0]=i;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
System.out.println("map.get(index2[0]) :"+map.get(index2[0]));
}).start();
}
}
}
Finally the map must pass following tests:
public class Task3Test {
static ConcurrentHashMap<Integer, String> map;
#BeforeClass
public static void fillMap(){
map = new ConcurrentHashMap<>();
timeIt(map);
}
#Test
public void elementPresenceTest(){
//GIVEN
//map;
//WHEN
List<Integer> actualPresenceList = Stream.iterate(0, i -> i + 1).limit(100)
.filter(n->(map.entrySet().stream().map(Map.Entry::getKey)
.anyMatch(m->(n.equals(m))))).collect(Collectors.toList());
actualPresenceList.forEach(System.out::println);
System.out.println("size"+actualPresenceList.size());
//THEN
List<Integer>expectedPresenceList = Stream.iterate(0, i -> i + 1).limit(100).collect(Collectors.toList());
assertThat(actualPresenceList, Matchers.contains(expectedPresenceList));
}
#Test
public void elementAmountTest() {
assertThat(map.entrySet(), Matchers.hasSize(100));
}
}
Iterator is not acceptable for concurrency. Solution is:
static Queue integerQueue = Stream.iterate(0, i -> i + 1).limit(100).collect(Collectors.toCollection(LinkedBlockingQueue::new));
There is needed to keep sleeping for the readMap() method to provide time for the writing method. If there is needed to keep any data structure on adding new elements in concurrency environment, it should be used queue instead of map.
In the example below if I implement ExecutorImpl without using Thread, then taskCompletionService.submit is blocked, even though it returns Future.
Is it possible to not block submit, but not use Thread in ExecutorImpl?
class ExecutorServiceTest {
private static class ExecutorImpl implements Executor {
public void execute(Runnable r) {
final Thread t = new Thread(new Runnable() {
public void run() {
r.run();
}});
t.start();
//If used will block others.
//r.run();
}
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
final Executor executor = new ExecutorImpl();
final CompletionService<String> taskCompletionService = new ExecutorCompletionService<>(executor);
int submittedTasks = 3;
for(int i = 0; i < submittedTasks; i++) {
final int j = i;
//here it is blocked if ExecutorServiceIml doesn't utilize Thread
taskCompletionService.submit(new Callable<String>() {
public String call() throws Exception {
Thread.sleep((3 - j) * 1000);
return "callable:" + String.valueOf(j);
}
});
System.out.println("Task " + String.valueOf(i) + " has been submitted...");
}
for(int tasksHandled=0; tasksHandled < submittedTasks; tasksHandled++) {
try {
final Future<String> result = taskCompletionService.take();
String l = result.get();
System.out.println("Task has completed - result: " + l);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
}
I'm new in adroid.
I like to do things when the color reach a value. I like (for example) show the alert if r is bigger than 30, but the application go in crash. Thank for very simple answares.
public class MainActivity extends Activity {
private AlertDialog dialog;
private AlertDialog.Builder builder;
private BackgroundColors view;
public class BackgroundColors extends SurfaceView implements Runnable {
public int grand=0;
public int step=0;
private boolean flip=true;
private Thread thread;
private boolean running;
private SurfaceHolder holder;
public BackgroundColors(Context context) {
super(context);
}
Inside this loop while running is true. is impossible to show dialogs ??
public void run() {
int r = 0;
while (running){
if (holder.getSurface().isValid()){
Canvas canvas = holder.lockCanvas();
if (r > 250)
r = 0;
r += 10;
if (r>30 && flip){
flip=false;
// *********************************
dialog.show();
// *********************************
// CRASH !!
}
try {
Thread.sleep(300);
}
catch(InterruptedException e) {
e.printStackTrace();
}
canvas.drawARGB(255, r, 255, 255);
holder.unlockCanvasAndPost(canvas);
}
}
}
public void start() {
running = true;
thread = new Thread(this);
holder = this.getHolder();
thread.start();
}
public void stop() {
running = false;
boolean retry = true;
while (retry){
try {
thread.join();
retry = false;
}
catch(InterruptedException e) {
retry = true;
}
}
}
public boolean onTouchEvent(MotionEvent e){
dialog.show();
return false;
}
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld){
super.onSizeChanged(xNew, yNew, xOld, yOld);
grand = xNew;
step =grand/15;
}
}
public void onCreate(Bundle b) {
super.onCreate(b);
view = new BackgroundColors(this);
this.setContentView(view);
builder = new AlertDialog.Builder(this);
builder.setMessage("ciao");
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Log.d("Basic", "It worked");
}
});
dialog = builder.create();
}
public void onPause(){
super.onPause();
view.stop();
}
public void onResume(){
super.onResume();
view.start();
}
}
you cann't show dialog in thread.you should use handler for this.create a handler in main thread and send it to your thread and instead of dialog.show() in your thread you should send message to handler and in handleMessage method of handler write dialog.show().
example:
Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
switch(msg.what) {
case 1:
dialog.show();
break;
}}};
and send message in thread:
handler.sendEmptyMessage(1);