How to make a class method only accesible by another class? - java

Suposse there are a "Worker" class in which one of its attributes is a queue of "WorkOrder" objects, and a "Boss" class which is the only one that can add or delete new "WorkOrders" of this queue. How could it be possible to make the method that modifies the queue only accessible by "Boss"?
I've thought of two solutions:
(a) Make the method package-private, keep the two classes in the same package and instantiate them in another.
(b) Make an interface with the methods that can be accessed by "Worker", make the constructor of this class private and create instead a static method which return an object with the same type than the interface.
What is your opinion? Can you think of a more elegant solution?

Consider having an interface that exposes the worker methods you want to be public. The boss can hold a reference to the implementation (which has the workorders queue getter) and only present the interface to other classes.
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
class Class {
public static void main(final String... args) {
final Boss boss = new Boss();
final Worker worker = boss.getWorker("sivmish");
worker.getWorkItems();//ERROR: only Boss has access to this.
}
}
interface Worker {
void processWork();
}
interface WorkOrder {
void doWork();
}
class WorkerImpl implements Worker {
private final Queue<WorkOrder> workItems;
WorkerImpl() {
this.workItems = new ArrayDeque<>();
}
public Queue<WorkOrder> getWorkItems() {
return workItems;
}
#Override
public void processWork() {
while (!workItems.isEmpty()) {
workItems.poll().doWork();
}
}
}
class Boss {
private final Map<String, WorkerImpl> workersByName;
Boss() {
workersByName = new HashMap<String, WorkerImpl>();
}
public Worker getWorker(final String name, WorkOrder... workOrders) {
if (!workersByName.containsKey(name)) {
final WorkerImpl worker = new WorkerImpl();
workersByName.put(name, worker);
}
final WorkerImpl worker = workersByName.get(name);
worker.getWorkItems().addAll(Arrays.asList(workOrders));
return worker;
}
}

I would rather suggest to keep the queue inside the Boss class,because you want to make it only accessible by the Boss for adding or removing
class Boss
{
public LinkedList<E> queue = new LinkedList<E>();
private void add(item)
{
//do stuff...
}
private void remove()
{//do stuff...}
public static void viewOnly()
{
//display details
}
}
class Workers
{
public workers()
{
Boss.viewOnly();
}
}
class Main
{
public static void main(String args[])
{
Boss b = new Boss();
b.add(1); //job 1
b.add(5); //job 5
/* and so on..
*/
workers w = new workers();
}
}

Related

Java Runnable without static reference

I am trying to learn multi-threading using the runnable interface but I am having some trouble figuring out how to pass information. Basically, in the example below, I want to remove the static reference from the Hashmap but if I do that, the program breaks. How do I pass the hashmap to the runnable interface class without using the static keyword?
public class ThreadDemo {
static HashMap <String, Integer>map = new HashMap<>();
public String Hi() {
return "hi";
}
public String Hello() {
return "Hello";
}
public void addToMap(String item) {
if (map.containsKey(item)) {
map.put(item, map.get(item) + 1);
} else {
map.put(item, 1);
}
}
public static void main(String[] args) throws InterruptedException {
ArrayList<Thread> all = new ArrayList<>();
for (int i = 0; i < 50; ++i) {
threader threader = new threader();
all.add(new Thread(threader));
}
for (Thread thread : all) {
thread.start();
}
for (Thread thread : all) {
thread.join();
}
ThreadDemo td = new ThreadDemo();
System.out.println(td.map);
}
}
And a class that implements Runnable
public class threader implements Runnable {
ThreadDemo td = new ThreadDemo();
#Override
public void run() {
synchronized(td.map) {
td.addToMap(td.Hi());
td.addToMap(td.Hello());
}
}
}
A class instance is all about information.
public class threader implements Runnable {
final private ThreadDemo td;
public threader(ThreadDemo td) {
this.td = td;
}
#Override
public void run() {
..
}
}
then to use (details omitted, just the idea):
ThreadDemo theTd = new ThreadDemo();
for (...) {
threader threader = new threader(theTd);
all.add(new Thread(threader));
}
....
Of course, all threads are using the same ThreadDemo, with the same map, so you'll need to ensure access is interlocked in some way, e.g., by using synchronized. The ThreadDemo.addToMap method should be synchronized in this example, rather than the caller of addToMap. This puts the responsibility for the "care of the map" into the place that actually owns the map, and is consequently a better design.
I chose to share the ThreadDemo rather than just the map inside the ThreadDemo, since it looks to me that the intent of ThreadDemo is just to be a wrapper around the map.

Junit for runnable class and Queue

I have a Processor class which implements Runnable.
The first method
Public Processor implements Runnable{
//"Event" is the name of this queue
PersistentQueue<Event> persistentQueue = new PersistentQueue<>("Event");
//add the Event POJO to the persistentQueue
public void addToQueue(Event, event) {
persistentQueue.add(event);
}
The persistentQueue is to store Event POJO
And the run method
public void run() {
while (true) {
if (!persistentQueue.isEmpty()) {
Event peekEvent = persistantQueue.peek();
sendRequest(peekEvent);
}
}
}
public void sendRequest(Event, event){
// do something to send the event
}
For the first addToQueue method I wrote the test
public class ProcessorTest {
private Event event;
private Processor m_Processor;
#Before
public void setup() throws IOException {
//the Processor class is a singleton
m_Processor = Processor.getProcessor();
event = new Event();
}
#Test
public void test(){
PersistentQueue<Event> persistentQueue = new PersistentQueue<>
("Event");
m_Processor.addToQueue(event);
assertEquals(1, persistentQueue.size());
}
}
But the queue size is 0 not 1. I dont know what's the problem. And I also have question about how to test the run method?
In your test method, you created a new queue that has nothing to do with your m_Processor instance; it goes unused entirely. You need to change your code so you can get the PersistentQueue instance contained inside your m_Processor instance. Assuming you have a getter method called getPersistentQueue inside Processor, then you can use the following:
#Test
public void test() {
m_Processor.addToQueue(event);
assertEquals(1, m_Processor.getPersistentQueue().size());
}

Passing parameter to anonymous class in Java

i'm trying to write anonymous inner class
interface Face{
void seeThis(String what);
}
class Eyes {
public void show(Face f){}
}
public class Seen {
public void test() {
Eyes e = new Eyes();
e.show(new Face() {
#Override
public void seeThis(String what){
System.out.print(what);
}
});
public static void main(String[] args) {
Seen s = new Seen();
s.test();
}
}
How to call seeThis() and how to pass parameter to it?
Method seeThis() belongs to Face class, which instance is anonymous and thus cannot be reached without storing reference to it. If you want to store a reference, you can do this in the following way:
public class Seen {
public Face face;
....
this.face = new Face() { ... };
e.show(this.face);
And then,
Seen s = new Seen();
s.face.seeThis();
Now, regarding passing the parameter. You have two options - declare parameter outside of anonymous class and make it final in order to be reachable by this anonymous class, or replace anonymous class with normal one and pass the parameter to its constructor:
Approach one:
final int parameter = 5;
...(new Face() {
#Override
public void seeThis() {
System.out.println(parameter);
}
});
Approach two:
public class MyFace implements Face() {
private final int parameter;
public MyFace(int parameter) {
this.parameter = parameter;
}
#Override
public void seeThis() {
System.out.println(parameter);
}
}
Then,
...
e.show(new MyFace(10));

Should I pass and store class references or make methods to get them from a central class?

I have a main class branching off to different classes which handle certain things.
Sometimes some of the classes need a method from a different class.
Currently I'm declaring and initiating the classes in my main class and then passing these objects to other classes that need them.
Example 1:
public class Main extends plugin {
private Walking walkClass;
private Sitting sitClass;
#Override
public void onEnable() {
walkClass = new Walking(this);
sitClass = new Sitting(this, walkClass);
}
//Methods
}
public class Walking {
Main mainClass;
public Walking(Main mainClass) {
this.mainClass = mainClass;
}
//Methods
}
public class Sitting {
Main mainClass;
Walking walkClass
public Sitting(Main mainClass, Walking walkClass) {
this.mainClass = mainClass;
this.walkClass = walkClass;
}
//Methods
}
Is okay to do this, or will it be better to create methods in the Central class to give references to other classes? In regards to Memory and CPU usage and Java practices.
Edit:
I'm comparing it to something like this;
Example 2:
public class Main extends plugin {
private Walking walkClass;
private Sitting sitClass;
private boolean started;
#Override
public void onEnable() {
started = true;
walkClass = new Walking();
sitClass = new Sitting();
}
public boolean isStarted() {
return started;
}
public Walking getWalking() {
return walkClass;
}
public Sitting getSitting() {
return sitClass;
}
}
public class Walking {
private Main mainClass;
private boolean walking;
public Walking(Main mainClass) {
this.mainClass = mainClass;
walking = mainClass.isStarted();
}
public boolean isWalking() {
if (mainClass.isStarted() {
return walking;
}
}
}
public class Sitting {
Main mainClass;
public Sitting(Main mainClass) {
this.mainClass = mainClass;
}
public boolean isSitting() {
return !mainClass.getWalking().isWalking();
}
}
I'm just worried that if I do it like in Example 1 and I store too many references to other instances it'll take up more memory than doing doing it like in Example 2.
Then if I do it like in Example 2, I'm worried that calling a method will add additional CPU tick(s) over if I did it as Example 1. I have no formal education in Java so I have no idea.
Though the fact that people would consider Example 1 the best practice is encouraging.

Read and write into shared thread variables

first of all i am new to threads and shared variables. So please be kind with me ;-)
I'm having a class called Routing. This class recieves and handles messages. If a message is of type A the Routing-Object should pass it to the ASender Object which implements the Runnable Interface. If the message is of type B the Routing-Class should pass it to the BSender Object.
But the ASender and BSender Objects have common variables, that should be stored into the Routing-Object.
My idea now is to declare the variables as synchronized/volatile in the Routing-Object and the getter/setter also.
Is this the right way to synchronize the code? Or is something missing?
Edit: Added the basic code idea.
RoutingClass
public class Routing {
private synchronized Hashtable<Long, HashSet<String>> reverseLookup;
private ASender asender;
private BSender bsender;
public Routing() {
//Constructor work to be done here..
reverseLookup = new Hashtable<Long, HashSet<String>>();
}
public void notify(TopicEvent event) {
if (event.getMessage() instanceof AMessage) {
asender = new ASender(this, event.getMessage())
} else if (event.getMessage() instanceof BMessage) {
bsender = new BSender(this, event.getMessage())
}
}
public synchronized void setReverseLookup(long l, Hashset<String> set) {
reverseLookup.put(l, set);
}
public synchronized Hashtable<Long, Hashset<String>> getReverseLookup() {
return reverseLookup;
}
}
ASender Class
public class ASender implements Runnable {
private Routing routing;
private RoutingMessage routingMessage;
public ASender(Routing r, RoutingMessage rm) {
routing = r;
routingMessage = rm;
this.run();
}
public void run() {
handleMessage();
}
private void handleMessage() {
// do some stuff and extract data from the routing message object
routing.setReverseLookup(somethingToSet)
}
}
Some comments:
Hashtable is a thread-safe implementation, you do not need another "synchronized" keyword see this and this for more information
Avoid coupling, try to work with interfaces or pass the hashtable to your senders, see this for more information
Depending on the amount of senders, you might want to use a ConcurrentHashMap, it greatly improves the performance, see ConcurrentHashMap and Hashtable in Java and Java theory and practice: Concurrent collections classes
This would conclude something like...:
public interface IRoutingHandling {
void writeMessage(Long key, HashSet<String> value);
}
public class Routing implements IRoutingHandling {
private final Hashtable<Long, HashSet<String>> reverseLookup;
private ASender asender;
private BSender bsender;
public Routing() {
//Constructor work to be done here..
reverseLookup = new Hashtable<Long, HashSet<String>>();
}
public void notify(TopicEvent event) {
if (event.getMessage() instanceof AMessage) {
asender = new ASender(this, event.getMessage())
} else if (event.getMessage() instanceof BMessage) {
bsender = new BSender(this, event.getMessage())
}
}
#Override
public void writeMessage(Long key, HashSet<String> value) {
reverseLookup.put(key, value);
}
}
public class ASender implements Runnable {
private IRoutingHandling _routingHandling;
public ASender(IRoutingHandling r, RoutingMessage rm) {
_routingHandling = r;
routingMessage = rm;
this.run();
}
public void run() {
handleMessage();
}
private void handleMessage() {
// do some stuff and extract data from the routing message object
_routingHandling.writeMessage(somethingToSetAsKey, somethingToSetAsValue)
}
}

Categories

Resources