Sending data within three threads in java, one after another - java

I wanted to make an elevator system where you send information from the following:
elevator (data) -> scheduler (buffer) -> floor (receive)
The Floor subsystem and the Elevators are the clients in the system; the Scheduler is the server.
when I pressed run some of the issues were:
class elevator is shown below:
package elevator;
import java.util.HashSet;
import java.util.Set;
public class elevator {
public enum State {
MOVING_UP, MOVING_DOWN, STOPPED
}
private int floor;
private State state;
#SuppressWarnings({ })
private Set<Integer> pressedButtons = (Set<Integer>) new HashSet<Integer>();
public elevator() {
state = State.STOPPED;
}
public int getFloor() {
return floor;
}
public void setFloor(int floor) {
this.floor = floor;
pressedButtons.remove(floor);
}
public State getState() {
return state;
}
public void setState(State s) {
state = s;
}
public boolean isMoving() {
return state == State.MOVING_UP || state == State.MOVING_DOWN;
}
public void buttonPressed(int i) {
pressedButtons.add(i);
}
public Set<Integer> getButtons() {
return pressedButtons;
}
public String toString() {
return "Floor: " + floor + "\n" + "\t State: " + state + "\n";
}
}
Exception in thread "Thread-0" java.lang.ClassCastException: class elevator.HashSet cannot be cast to class java.util.Set (elevator.HashSet is in unnamed module of loader 'app'; java.util.Set is in module java.base of loader 'bootstrap')
at elevator.elevator.(elevator.java:21)
at elevator.elevatorExchange.retrieveData(elevatorExchange.java:30)
at elevator.elevatorExchange.run(elevatorExchange.java:19) at java.base/java.lang.Thread.run(Thread.java:835)
Thread 1: elevator
package elevator;
import java.util.concurrent.BlockingQueue;
public class elevatorExchange implements Runnable{
private BlockingQueue<elevator> messages;
public elevatorExchange(BlockingQueue<elevator> messages) {
this.messages = messages;
}
#Override
public void run() {
try {
elevator elevatorData = retrieveData();
messages.put(elevatorData);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private elevator retrieveData() throws InterruptedException {
Thread.sleep(5000);
elevator elevatorData = new elevator();
return elevatorData;
}
}
Thread 2: Scheduler. Scheduler is only being used as a communication channel from the Floor thread to the Elevator thread
package scheduler;
import java.util.concurrent.BlockingQueue;
import elevator.elevator;
public class Scheduler implements Runnable {
private BlockingQueue<elevator> messages;
public Scheduler(BlockingQueue<elevator> messages) {
this.messages = messages;
}
#Override
public void run() {
elevator elevatorData = messages.take();
}
Thread 3: The floor (this will receive it from the scheduler). This is the part I'm struggling with the most, I am trying to make sure the data passed down to the floor is from the scheduler and not the elevator, but my IDE keeps making changes to the data type that's running a lot of exceptions.
package floor;
import java.util.concurrent.BlockingQueue;
import elevator.elevator;
public class FloorReceiver implements Runnable{
private BlockingQueue<elevator> messages;
public FloorReceiver(BlockingQueue<elevator> messages) {
this.messages = messages;
}
#Override
public void run() {
try {
System.out.println("waiting for data from elevator");
elevator elevatorData = messages.take();
System.out.println("data from elevator" + elevatorData);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Testing:
package floor;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import elevator.elevator;
import elevator.elevatorExchange;
public class elevatorToFloorTest {
public static void main(String[] args) {
BlockingQueue<elevator> messages = new ArrayBlockingQueue<elevator>(1);
elevatorExchange retriever = new elevatorExchange(messages);
FloorReceiver receiver = new FloorReceiver(messages);
new Thread(retriever).start();
new Thread(receiver).start();
}
}

This line is the problem:
private Set<Integer> pressedButtons = (Set<Integer>) new HashSet<Integer>();
The exception message tells us that the HashSet is not a java.util.HashSet but is something you wrote:
class elevator.HashSet cannot be cast to class java.util.Set
i.e., the HashSet is defined in the elevator package.
Your HashSet is not implementing the Set interface. If it were, then you would not need the cast. Since it isn't, the cast cannot magically make it work.
It seems the compiler would have told you, except you used #SuppressWarnings. (I'm not sure what the empty list does).
On the other hand, the code for the elevator class that you have now posted shows an import for java.util.HashSet, not a homebrew implementation. This cannot produce the error shown. Have you failed to rebuild everything?

Related

custom naming for threads using threadfactory

I have a class that represent the world where subjects live in
public class WorldLifecycle {
private ExecutorService executorService;
public void startWorld() {
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(),
r -> {
String id = ((IdentifiableRunnable) r).getId();
return new Thread(r, id);
});
}
public void bringLife(LivingPerson ... people) {
Arrays.stream(people).forEach(executorService::submit);
}
public void endWorld() {
executorService.shutdownNow();
try {
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
System.err.println("Failed to finish thread executor!");
}
}
}
Every LivingPerson looks like this
public class LivingPerson implements IdentifiableRunnable {
// investigate global world variable
private boolean isRunning = true;
private final StatefulPerson person;
public LivingPerson(StatefulPerson person) {
this.person = person;
}
#Override
public void run() {
System.out.println("Initial state: person=" + person.getRawPerson());
while (isRunning) { // for now forever
try {
Thread.sleep(1000); // do transition every 1 seconds
LifeState state = person.nextState();
System.out.println(getPerson().getName() + " " + state.getActionLabel());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("End state: person=" + person.getRawPerson());
}
#Override
public String getId() {
Person person = getPerson();
return person.getId() + " - " + person.getName();
}
#Override
public void terminate() {
isRunning = false;
}
// returns clone instead of existing
private Person getPerson() {
return person.getRawPerson();
}
}
I want to name each thread by using person's name and unique identifier.
IdentifiableRunnable is a simple interface
public interface IdentifiableRunnable extends Runnable {
String getId();
void terminate();
}
I initialize everything like this
WorldLifecycle world = new WorldLifecycle();
LivingPerson male = createPerson("John", 40, Gender.MALE);
LivingPerson female = createPerson("Helen", 25, Gender.FEMALE);
System.out.println("Starting world...");
world.startWorld();
world.bringLife(male, female);
// just wait
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("Destroying world...");
world.endWorld();
But when I try to run it, I get the error
Exception in thread "main" java.lang.ClassCastException: java.util.concurrent.ThreadPoolExecutor$Worker cannot be cast to com.lapots.breed.lifecycle.api.Ide
ntifiableRunnable
at com.lapots.breed.lifecycle.WorldLifecycle.lambda$startWorld$0(WorldLifecycle.java:14)
at java.util.concurrent.ThreadPoolExecutor$Worker.<init>(ThreadPoolExecutor.java:612)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:925)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1357)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at com.lapots.breed.lifecycle.WorldLifecycle.bringLife(WorldLifecycle.java:20)
at com.lapots.breed.Sandbox.main(Sandbox.java:23)
As it seems it does not get my identifiableRunnable in the ThreadFactory.
How to solve it?
If you trace library calls with a debugger you will notice that your newThread method will be called like so:
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
So it is passed an instance of the Worker class, which obviously can't be cast to your IdentifiableRunnable.
To execute your stream in parallel you should use ForkJoinPool how it is described in this post, in the first answer Custom thread pool in Java 8 parallel stream
Btw, here's how you can compress the code in your post:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.stream.Stream;
public class Main {
interface TestInterface extends Runnable{
default String getId() {
return "2";
}
}
static class TestClass implements TestInterface {
#Override
public void run() {
System.out.println("TEST");
}
}
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
#Override
public Thread newThread(final Runnable r) {
String id = ((TestInterface)r).getId();
Thread t = new Thread(r, id);
t.setDaemon(true);
return t;
}
});
Stream.of(new TestClass(),new TestClass(),new TestClass(),new TestClass()).forEach(exec::submit);
}
}

Run method inside a method in java

I'm sending more than 1 request to a web service, below there is an example of that requests. Its important for my application to get the answer from the web service so if there is an exception application will try couple of times to get the answer.
Because of that getting something simple like
deviceList = serviceAdapter.getDevices(); is turn into below code.
boolean flag = true;
int counter = 1;
List<Device> deviceList = null;
while (flag) {
try {
deviceList = serviceAdapter.getDevices();
flag = false;
} catch (Exception e) {
try {
if (counter == 5) {
System.out.println("Timeout Occured!");
flag = false;
} else {
Thread.sleep(1000 * counter);
counter++;
}
} catch (InterruptedException e1) {
}
}
}
And in my application i have lots of requests which means there will be more ugly codes. Is there a way where i will call my request methods as parameter for another method something like this:
deviceList = wrapperMethod(serviceAdapter.getDevices());
Problem is there will be different type of requests, so they will return different type objects (list,array,string,int) and their paramaters will change. Is there a suitable solution in java for this problem?
You can pass a Supplier<T> to the wrapperMethod:
public static <T> T wrapperMethod (Supplier<T> supp) {
boolean flag = true;
int counter = 1;
T value = null;
while (flag) {
try {
value = supp.get();
flag = false;
} catch (Exception e) {
try {
if (counter == 5) {
System.out.println("Timeout Occured!");
flag = false;
} else {
Thread.sleep(1000 * counter);
counter++;
}
} catch (InterruptedException e1) {
}
}
}
}
And call it with:
List<Device> deviceList = wrapperMethod (() -> serviceAdapter.getDevices());
I'm afraid, though, that it will limit the methods you call within the lambda expression to throw only RuntimeExceptions.
You can use some command implementation to execute some specific codes :
Here is a simple example of a command
interface Command{
void run();
}
And a couple of implementations :
class SayHello implements Command{
#Override
public void run() {System.out.println("Hello World");}
}
class KillMe implements Command{
public void run() { throw new RuntimeException();};
}
All we have to do to execute those method is to receive an instance of Command and run the method :
public static void execCommand(Command cmd) {
cmd.run();
}
And to use this
public static void main(String[] args) {
execCommand(new SayHello());
execCommand(new KillMe());
}
Hello World
Exception in thread "main" java.lang.RuntimeException
It also accepts lambda expression :
execCommand(() -> System.out.println("Say goodbye"));
And method reference :
public class Test{
public static void testMe() {
System.out.println("I work");
}
}
execCommand(Test::testMe);
Note that I didn't specify that this could throw Exception so I am limited to unchecked exception like RuntimeException but of course void run() throws Exception could be a solution. That way you can do what ever you want.
Full example (with exceptions) :
public class Test {
public static void main(String[] args) {
try {
execCommand(new SayHello());
execCommand(() -> System.out.println("Say goodbye"));
execCommand(Test::testMe);
execCommand(new KillMe());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void testMe() throws IOException{
System.out.println("I work");
}
public static void execCommand(Command cmd) throws Exception {
cmd.run();
}
}
interface Command{
void run() throws Exception;
}
class SayHello implements Command{
#Override
public void run() {System.out.println("Hello World");}
}
class KillMe implements Command{
public void run() { throw new RuntimeException();};
}
Output:
Hello World
Say goodbye
I work
Exception in thread "main" java.lang.RuntimeException
at main.KillMe.run(Test.java:39)
at main.Test.execCommand(Test.java:25)
at main.Test.main(Test.java:17)
You can use #RetryOnFailure annotation from jcabi-aspects
Create a wrapper method then annotate it to enable auto retry upon Exception
As an example:
#RetryOnFailure(attempts = 5)
List<Device> retryWhenFailed(ServiceAdapter serviceAdapter) throws Exception {
return serviceAdapter.getDevices();
}
This solution uses Generics to be able to handle different Object with most of the same code and a Runnable to execute the fetching.
With this solution, you would need only to write the different adapters extending from ServiceAdapter<T extends Fetchable> to implement the logic to fetch the data for each different class (which would have to implement Fetchable).
Define an interface that abtracts the objects that can be fetched by the different services.
package so50488682;
public interface Fetchable {
}
The ojbect that are to be retrieved implement this interface so you can use the same code for different classes.
package so50488682;
public class Device implements Fetchable{
private String id;
public Device(String id) {
this.id = id;
}
public String toString() {
return "I am device " + id;
}
}
Define an abstract ServiceAdapter that the different service adapters will extend to implement the logic for each kind of object to be retrieved. We add throws Exception to the get() method so this method cand just delegate the exception handling to the FetcherService and decide if it should retry or fail.
package so50488682;
import java.util.List;
public abstract class ServiceAdapter<T extends Fetchable> {
public abstract List<T> get() throws Exception;
}
This is an example of an implementation done to get objects of class Device.
package so50488682;
import java.util.ArrayList;
import java.util.List;
public class DeviceServiceAdapter extends ServiceAdapter<Device>{
#Override
public List<Device> get() throws Exception{
List<Device> rtn = new ArrayList<>();
// fetch the data and put it into rtn, this is a mock
Device d = new Device("1");
rtn.add(d);
d = new Device("2");
rtn.add(d);
d = new Device("3");
rtn.add(d);
//
return rtn;
}
}
Finally this is a generic solution to run the different service adapters.
public class FetcherService<T extends Fetchable> implements Runnable{
List<T> result = new ArrayList<>();
ServiceAdapter<T> serviceAdapter;
#Override
public void run() {
boolean flag = true;
int counter = 1;
while (flag) {
try {
result = serviceAdapter.get();
flag = false;
} catch (Exception e) {
try {
if (counter == 5) {
System.out.println("Timeout Occured!");
flag = false;
} else {
Thread.sleep(1000 * counter);
counter++;
}
} catch (InterruptedException e1) {
throw new RuntimeException("Got Interrupted in sleep", e);
}
}
}
}
public List<T> getResult() {
return result;
}
public void setResult(List<T> result) {
this.result = result;
}
public void setAdapter(ServiceAdapter<T> adapter) {
this.serviceAdapter = adapter;
}
}
From the main or calling program it work like this:
package so50488682;
import java.util.List;
public class SO50488682 {
public static void main(String args[]) {
try {
DeviceServiceAdapter deviceServiceAdapter = new DeviceServiceAdapter();
FetcherService<Device> deviceFetcherService = new FetcherService<>();
deviceFetcherService.setAdapter(deviceServiceAdapter);
deviceFetcherService.run();
List<Device> devices = deviceFetcherService.getResult();
for(Device device : devices) {
System.out.println(device.toString());
}
}catch(Exception e) {
System.out.println("Exception after retrying a couple of times");
e.printStackTrace();
}
}
}

Java - Thread doesn't want to start

I have this console application, but for some reason the thread's run() method doesn't want to start. The code seems long for the first time but I tried to organize it as much as I can.
The result output:
eThread starting!!
So it seems that CarManager.startFunctionalities() gets executed, but the line eThread.start() is not executed at all because the line "started" is not printed out.
Here is the sourcecode.
The main class:
package rpicar.android;
public class AndroidEmulator{
public static void main(String args[]) throws InterruptedException {
CarManager cm = new CarManager ("localhost");
}
}
CarManager:
package rpicar.android;
import rpicar.common.Direction;
import rpicar.common.EnvironmentData;
public class CarManager {
private MotorManager mManager;
private final String RPIADDRESS = "localhost";
private Thread mThread; //motor
private EnvironmentManager eManager;
private Thread eThread;
public CarManager(String rpiAddress) {
//initialize MotorManager
mManager = new MotorManager(RPIADDRESS);
//Make a thread for the Motor commands
mThread = new Thread(mManager);
//Initialize EnvironmentManager
eManager = new EnvironmentManager(RPIADDRESS);
//Makea thread for collecting EnvironmentData
eThread = new Thread (eThread);
startFunctionalities();
}
public void move(Direction d){
this.mManager.setDirection(d);
}
public EnvironmentData getCurrentEnvironmentData(){
return this.eManager.getCurrentEnvironmentData();
}
private void startFunctionalities(){
//Start MotorManager for sending movement commands when needed.
//mThread.start();
//Start EnvironmentManager to collect EnvironmentData
System.out.println("eThread starting!! ");
eThread.start();
}
}
EnvironmentManager:
package rpicar.android;
import rpicar.common.CarComponent;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import rpicar.common.EnvironmentData;
public class EnvironmentManager extends CarComponent implements Runnable{
private EnvironmentData currentEnvironmentData;
public EnvironmentManager(String rpiAddress) {
super(rpiAddress, 2176, true);
this.currentEnvironmentData = new EnvironmentData();
}
public synchronized EnvironmentData getCurrentEnvironmentData() {
return currentEnvironmentData;
}
public synchronized void setCurrentEnvironmentData(EnvironmentData currentEnvironmentData) {
this.currentEnvironmentData = currentEnvironmentData;
}
#Override
public void run() {
System.out.println("eThread started!! ");
super.connect();
while(true){
try {
this.setCurrentEnvironmentData((EnvironmentData) super.in.readObject());
} catch (IOException ex) {
super.connect();
} catch (ClassNotFoundException ex) {
Logger.getLogger(EnvironmentManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
When you create your instance of eThread, you accidentally pass the thread itself to the constructor (or according to the order of the operations, you pass null).
You should pass eManager to the constructor instead.
eThread = new Thread (eThread);
Would become
eThread = new Thread (eManager);
You can protect yourself in the future from this mistake by making the eThread a final field, so you cannot use it before you declare it.

Getting a result in the future?

I'm looking to get a result from a method which can take a while to complete and doesn't actually return the object, so I'd like to deal with it as effectively as possible. Here's an example of what I'm trying to achieve:
public static void main (String[] args) {
Object obj = someMethod();
System.out.println("The object is" + obj + ", wooh!");
}
public void callObject() {
// Sends request for the object
}
public void receiveObject(Object object) {
// Received the object
}
public Object someMethod() {
callObject();
// delay whilst the object is being received
// return received object once received, but how?
}
The method callObject will call to get the object, however a different method is called with the object in. I want someMethod() to be able to call for the object, and then return what it eventually receives, even though the actual call and receive are separate methods.
I've looked into using FutureTasks and Callables which I think is the way forward, I'm just not too sure how to implement it.
Sorry if I didn't explain myself too well, I'll give more information if necessary.
Thanks!
You could write a method, that kicks of some long running task asynchronously. You would then return a future object, that is empty but gets filled when the long running task is completed. In other programming languages, this is called a promise.
Here is an simple example. I created a method called someLongAsyncOperation which executes something that takes a while. To simulate this, I just sleep for 3 seconds before generating an answer.
import java.util.UUID;
import java.util.concurrent.*;
public class Test {
private static final ExecutorService executorService = Executors.newSingleThreadExecutor();
public Future<MyAnswer> someLongAsyncOperation(){
Future<MyAnswer> future = executorService.submit(() -> {
Thread.sleep(3000);
return new MyAnswer(UUID.randomUUID().toString());
});
return future;
}
public static void main(String[] args) throws Exception {
System.out.println("calling someLongAsyncOperation ...");
Future<MyAnswer> future = new Test().someLongAsyncOperation();
System.out.println("calling someLongAsyncOperation done.");
// do something else
System.out.println("wait for answer ...");
MyAnswer myAnswer = future.get();
System.out.printf("wait for answer done. Answer is: %s", myAnswer.value);
executorService.shutdown();
}
static class MyAnswer {
final String value;
MyAnswer(String value) {
this.value = value;
}
}
}
If you execute this little test class, you'll see, that someLongAsyncOperation returns fast, but when calling future.get(); we wait for the operation to complete.
You could now do something like starting of more than one longAsyncOperation, so they would run in parallel. And then wait until all of them are done.
Does this work as a starting point for you?
EDIT
You could implement someMethod like this:
public MyAnswer someMethod() throws ExecutionException, InterruptedException {
Future<MyAnswer> future = someLongAsyncOperation(); // kick of async operation
return future.get(); // wait for result
}
Which will make the async operation synchron again, by calling it and waiting for the result.
EDIT2
Here's another example that uses wait/notify:
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test2 {
private static final ExecutorService executorService = Executors.newSingleThreadExecutor();
private Object receivedObject;
private final Object mutex = new Object();
public static void main (String[] args) throws InterruptedException {
Object obj = new Test2().someMethod();
System.out.println("The object is" + obj + ", wooh!");
executorService.shutdown();
}
public void callObject() {
System.out.println("callObject ...");
// Sends request for the object asynchronously!
executorService.submit(() -> {
// some wait time to simulate slow request
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// provide object to callback
receiveObject(UUID.randomUUID().toString());
});
System.out.println("callObject done.");
}
public void receiveObject(Object object) {
System.out.println("receiveObject ...");
synchronized (mutex) {
this.receivedObject = object;
mutex.notify();
}
System.out.println("receiveObject done.");
}
public Object someMethod() throws InterruptedException {
System.out.println("someMethod ...");
synchronized (mutex) {
callObject();
while(this.receivedObject == null){
mutex.wait();
}
}
System.out.println("someMethod done.");
return this.receivedObject;
}
}
someMethod waits until receivedObject exists. receiveObject notifies upon arrival.
You need a callback:
private abstract class Callback<T>{
run(T object);
}
public Object someMethod() {
callObject(new Callback<Object>()
{
#Override
public void run(Object object)
{
System.out.println("The object is" + object + ", wooh!");
}
})
}
public void callObject(Callback<Object> callback) {
// Sends request for the object
callback.run(object);
}
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class ThreadExample implements Callable<String>{
#Override
public String call() throws Exception {
// TODO Auto-generated method stub
return "Ashish";
}
}
public class FutureThreadExample {
public static void main(String a[]) throws InterruptedException, ExecutionException {
ExecutorService executorService=Executors.newFixedThreadPool(1);
List <Future<String>>objList=new ArrayList<Future<String>>();
for(int i=0;i<10;i++) {
Future<String> obj=executorService.submit(new ThreadExample());
objList.add(obj);
}
for( Future<String> fut:objList) {
System.out.println(fut.get());
}
executorService.shutdown();
}
}

how to use a synchronized linked hash map correctly

trying to make an lru map by subclassing linked hash map.
the map is run through collections.synchronized.
all usages of the map are surrounded by a synchronized block. the unit test also fails if they are all removed. one would think they are not necessary since the map was run through collections.synchronized.
one thread puts sequential numbers (0,1,2,3 ...) into the map. removals are handled by removed eldest entry. no one else removes entries from the map.
the other thread gets the data from the map.
the following unit test fails usually at "oops". this is when a non zero number shows up in the first position (it should be zero until the map gets full). other strange things can happen like null values in the entry set.
any pointers will be appreciated.
thanks
import static org.junit.Assert.*;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
class LruMap<K,V> extends LinkedHashMap<K,V> {
public LruMap() {
super(defaultMaxSize+1,.75f,true);
maxSize=defaultMaxSize;
}
public LruMap(int arg0) {
super(arg0+1,.75f,true);
maxSize=arg0;
}
public LruMap(int arg0,float arg1) {
super(arg0+1,arg1,true);
maxSize=arg0;
}
public LruMap(int arg0,float arg1,boolean arg2) {
super(arg0+1,arg1,arg2);
if(!arg2)
throw new RuntimeException("you did not construct an lru map!");
maxSize=arg0;
}
public LruMap(Map<K,V> arg0) {
super(arg0);
throw new RuntimeException("you did not construct an lru map!");
}
public boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return size()>maxSize;
}
public final int maxSize;
public static final int defaultMaxSize=2048;
static final long serialVersionUID=0;
}
class Server implements Runnable {
public Server(final int pieces,final int period) {
this.pieces=pieces;
this.period=period;
lruMap=Collections.synchronizedMap(new LruMap<Long,Long>(3*pieces/2));
}
#Override public void run() {
t0=System.currentTimeMillis();
while(piece<stopAtPiece) {
final long dt=System.currentTimeMillis()-t0;
final long target=piece(dt);
System.out.println("adding "+(target-piece+1)+" items");
for(;piece<=target;piece++) {
synchronized(lruMap) {
lruMap.put(piece,piece);
}
}
checkMap(piece,true);
try {
Thread.sleep(100);
} catch(InterruptedException e) {
e.printStackTrace();
break;
}
}
}
Map.Entry<Long,Long>[] checkMap(final long n,boolean print) {
synchronized(lruMap) {
Map.Entry<Long,Long>[] entries=null;
if(lruMap.size()>0) {
final Set<Map.Entry<Long,Long>> entrySet=lruMap.entrySet();
entries=new Map.Entry[entrySet.size()];
entrySet.toArray(entries);
long first=entries[0].getKey();
long last=entries[entries.length-1].getKey();
if(print)
for(Map.Entry<Long,Long> entry:entries)
System.out.print(entry.getKey()+" ");
System.out.println();
if(n<pieces&&first!=0) {
System.out.println("lru: first!=0! "+first);
if(throwWhenfirstIsNotZero) { throw new RuntimeException("oops"); }
}
for(int i=0;i<entries.length-1;i++) {
long p0=entries[i].getKey();
long p1=entries[i+1].getKey();
if(p0>p1)
System.out.println("out of order! "+p0+" "+p1);
else if(p0==p1)
System.out.println("dupicate "+p0+" "+p1);
else if(p0+1==p1)
; // ok
else if(p0+1<p1)
System.out.println("skipped "+p0+" "+p1);
else System.out.println("some case i mssed!");
}
}
return entries;
}
}
public long piece(final long dt) {
return dt/period*pieces+dt%period*pieces/period;
}
public boolean throwWhenfirstIsNotZero=true;
protected long piece;
public long t0;
protected long stopAtPiece=Long.MAX_VALUE;
public final int period;
public final int pieces;
public final Map<Long,Long> lruMap;
}
public class ServerTestCase {
#Before public void setUp() throws Exception {}
#After public void tearDown() throws Exception {}
#Test public void testRun() {
server.stopAtPiece=server.pieces;
server.throwWhenfirstIsNotZero=true;
Thread thread=new Thread(server);
thread.setName("server");
thread.start();
while(thread.isAlive()) {
for(long i=0;i<server.piece;i++)
synchronized(server.lruMap) {
server.lruMap.get(i);
}
}
}
final int period=2*1000;
final int serverPieces=100;
Server server=new Server(serverPieces,period);
}
If you are accessing the collection inside a synchronized(lruMap) block, then you probably don't want to wrap it in Collections.synchronizedMap() - use one or the other. This is because they will probably be using different locks - in fact it's almost certain, because it's extremely unlikely that synchronizedMap() is using synchronized(this) internally.
Also I recommend enter link description here

Categories

Resources