I'm a Java student and this is my attempt of implementing a StackExchange (there's a pusher thread and a popper thread, a single stack resource and two controlling Threads for the stack content and time passing).
I was hoping if someone could comment my code for improvements or errors\bad practices, even if the code seems to work.
The main reason of this program was to figure out how to control resource access in a multithreading environment.
I have concerns about the use of the ScheduledThreadPoolExecutor rather than locking(the stack), and my usage of synchronized in the StackExchange class methods(for accessing the stack), I would like to spawn free threads working on a dynamically locked resource. Any advice?
NB:"Format of magic numbers and syso's may be awful for testing porpuses
code here:
package examples;
import java.util.Random;
import java.util.Stack;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.swing.JOptionPane;
public class StackExchange {
/*
* Two Threads playing with a stack, a timer and a controller for the stack that permits to exit
* */
public class Popper implements Runnable
{
StackExchange sEx;
public Popper(StackExchange sex)
{
this.sEx=sex;
}
#Override
public void run() {
System.out.println("Popper: popping!\t"+sEx.getPeek());
sEx.callTheStack(this, null);
}
}
public class Pusher implements Runnable
{
StackExchange sEx;
public Pusher(StackExchange sex)
{
sEx=sex;
}
#Override
public void run() {
System.out.println("Pusher: pushing!\t");
sEx.callTheStack(this, "Hi!");
}
}
public class StackController implements Runnable
{
private Stack<String> theStack;
public int waiting=5;
public StackController(Stack<String> theStack, String name) {
this.theStack = theStack;
Thread.currentThread().setName(name);
}
#Override
public void run()
{
Random rand = new Random();
waiting = rand.nextInt(10);
StringBuilder buffer = new StringBuilder();
int i=0;
for(String string: theStack)
{
buffer.append(string+"\n");
i++;
}
buffer.append("\nFound "+i+" elements\nIWillWait4:\t"+waiting);
System.out.println("\t\t\t\t\t\t\t\t"+Thread.currentThread().getName().toString()+" Says:" + buffer.toString());
if(i>1)
{
System.out.println("ERRER");
System.exit(0);
}
if(i==1 && JOptionPane.showConfirmDialog(null, "found 1 element\nWannaStop?")==0)
System.exit(0);
}
}
public class Timer implements Runnable{
#Override
public void run() {
StackExchange.time++;
System.out.println("Time Passed:\t"+StackExchange.time+" seconds");
}
}
/*
* implementation of the StackExchange class
* */
private Popper popper;
private Pusher pusher;
private StackController stackController;
private StackController secondSC;
private Timer timer;
static int time=0;
private Stack<String> stack;
public StackExchange()
{
timer = new Timer();
stack = new Stack<String>();
pusher = new Pusher(this);
popper = new Popper(this);
stackController = new StackController(this.getStack(), "FirstStackController");
}
public static void main(String[] args) {
StackExchange sex = new StackExchange();
sex.start();
System.out.println("Num of Threads:"+Thread.activeCount());
}
public void start()
{
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(5);
exec.scheduleAtFixedRate(timer, 0, 1, TimeUnit.SECONDS);
exec.scheduleAtFixedRate(pusher, 0, 2, TimeUnit.SECONDS);
exec.scheduleAtFixedRate(popper, 1, 2, TimeUnit.SECONDS);
exec.scheduleAtFixedRate(stackController, 0, stackController.waiting, TimeUnit.SECONDS);
}
public Stack<String >getStack()
{
return this.stack;
}
public void callTheStack(Object caller, String pushedString)
{
synchronized(this)
{
if(caller instanceof Popper)
stack.pop();
else if(caller instanceof Pusher)
stack.push(pushedString);
}
}
public String getPeek()
{
synchronized(this)
{
return stack.peek();
}
}
}
Things that might help:
Don't use java.util.Stack.
A more complete and consistent set of LIFO stack operations is
provided by the Deque interface and its implementations, which should
be used in preference to this class.
http://docs.oracle.com/javase/8/docs/api/java/util/Stack.html
Your nested subclasses of StackExchange are all inner classes so
that means they already have a reference to the containing
StackExchange instance
and its member stack instance, which should be final.
So don't pass them as parameters. This simplifies logic, maintenance,
and GC.
caller instanceof Popper this type of reflection is utterly
unnecessary and breaks object orientation.
You know that Object is too broad a type for callTheStack (weak
name). In fact, you know that the object will be a Runnable, but
more importantly, the Runnable should know what to do already.
Synchronization should be kept minimal to just the critical section that shares data and no more, shown below using the synchronized keyword
or to just the memory boundary, shown below using the volatile keyword
and member variables of a containing class are a great way to share data between threads within the class.
Example
public class StackExchange {
private final Deque<String> stack = new ArrayDeque<>();
private volatile boolean running;
private void consume(String item) {
// ...
}
private String obtain() {
// ...
}
private boolean getPermission() {
// ...
}
// getters, setters, ...
private final Runnable consumer = new Runnable() {
#Override
public void run() {
while (running) {
final String popped;
synchronized(stack) {
popped = stack.pollFirst();
}
consume(popped);
}
}
};
private final Runnable producer = new Runnable() {
#Override
public void run() {
while (running) {
final String pushing = obtain();
synchronized(stack) {
stack.offerFirst(pushing);
}
}
}
};
public static void main(String ... args) {
StackExchange exchange = new StackExchange();
exchange.setRunning(true);
new Thread(exchange.getConsumer()).start();
new Thread(exchange.getProducer()).start();
do {
} while (exchange.getPermission());
exchange.setRunning(false);
}
}
It's a good idea to declare member variables prior to member methods.
I put the Runnable code in anonymous classes to leave the code at the very edge of using lambdas.
The idea behind consume, obtain, and getPermission is to hint at how the code would interact with the business logic that doesn't know about threading. These could be implemented as callbacks or abstract methods.
One good thing about Deque is that it can easily be set up for a FIFO queue.
Just for fun, convert those Runnable instances into lambdas, and make the StackExchange class generic.
Hot question: what other subtypes of Deque<E> might suit, and what advantages or disadvantages would they have? What code changes might need to happen to accommodate them?
Related
I have an array of int with size 4, only one thread can access an array cell at a time.
I thought about using Semaphore but I don't know how or if there is a way to get the acquired index
I build a code example to explain butter:
public class Temp {
private ExecutorService executeService;
private Semaphore semaphore;
private int[] syncArray; // only one thread can access an array cell at the same time
public Temp() {
syncArray = new int[]{1,2,3,4};
executeService = Executors.newFixedThreadPool(10);
semaphore = new Semaphore(syncArray.length, true);
for(int i = 0;i < 100; i++) {
executeService.submit(new Runnable() {
#Override
public void run() {
semaphore.acquire();
// here I want to access one of the array cell
// dose not matter witch one as long as no other thread is currently use it
int syncArrayIndex = semaphore.getAcquiredIndex(); // is something like this possible?
syncArray[syncArrayIndex] += ...;
semaphore.release();
}
});
}
}
}
Edit:
this is a piece of code that looks closer the my real problem:
public class Temp {
private ExecutorService executeService;
private Semaphore semaphore;
private static ChromeDriver driver;
public Temp() {
executeService = Executors.newFixedThreadPool(10);
}
public Future<WikiPage> getWikiPage(String url) {
executeService.submit(new PageRequest(url) {
});
}
private static class PageRequest implements Callable<WikiPage> {
String url;
public PageRequest(String url) {
this.url = url;
}
#Override
public WikiPage call() throws Exception {
String html = "";
synchronized (driver) {
html = ...// get the wiki page, this part takes a log time
};
WikiPage ret = ...// parse the data to the WikiPage class
// this part takes less time but depend on the sync block above
return ret;
}
}
}
#Kayaman I'm not sure I understand your comment, the problem is that I return a future. Do you have a any suggestions on how to improve my code to run faster?
No, semaphore isn't useful here. It only knows about how many permits it has, there are no "indices" in a semaphore.
You can use AtomicIntegerArray instead, although if you explain your root problem, there may be a more suitable class to use.
So, I am new to threads, and I'm still learning how everything works. So, I couldn't find an answer that would provide an explanation for my problem (to my level of understanding).
I have a Runnable class that looks like so:
public class Request implements Runnable {
private Boolean ok = true;
public synchronized void setOk(Boolean ok) {
this.ok = ok;
}
public synchronized Boolean getOk() {
return ok;
}
private synchronized void foo() {
//if something happens
setOk(false);
}
#Override
public void run() {
while (true)
foo();
}
}
And then I have another class that does the following:
private static Request request;
private static void spawnThreads() {
ExecutorService e = new Executors.newFixedThreadPool(4);
request = new Request();
e.execute(request);
}
public static void main(String[] args) {
spawnThreads();
while (true) {
System.out.println(request.getOk());
if (!request.getOk())
request.setOk(true);
TimeUnit.SECONDS.sleep(10);
}
}
I need that if in the main thread, that getOk() returns false, do something and set it to true. Viceversa, set it to false in the thread (which I need to keep on going, no matter what the value of ok is at any given time).
As this code is, I can't get the value of request.getOk() in the main thread. If I remove the synchronized words from the getter and setter, I can access the value in the main thread until a point in time when it is changed by the thread, and never again.
Also, the executor is used because I would create multiple Request objects, and waiting for it to shutdown before accessing the variable would contradict my reason for doing this, as I would need all the threads to keep running.
That thread is making http requests to a server (that randomly times out, denies response, etc) and is used to retrieve some information. The ok variable is there to take a note when the thread acquires an ok response and some information from the server.
How do I solve it so that the thread can update that variable, but the main thread to be able to retrieve it whenever needed, no matter if it was changed by the thread in the meanwhile or not.
Would changing my Runnable to a Callable help? If yes, how?
Your example still leaves some holes in the thread-safety. Like mentioned by #Radiodef using AtomicBoolean can relieve you of most of the synchronisation if used properly.
Using your example, this is a thread safe Request class that accepts a message, like an answer to a http request.
public final class Request implements Runnable {
private final AtomicBoolean ok = new AtomicBoolean(false);
// volatile variables promote reference changes through all threads
private volatile String msg;
private boolean setMessage(String responseMessage) {
if (this.ok.compareAndSet(false, true)) {
this.msg = msg;
return true;
}
return false;
}
public boolean hasMessage() {
// *pure* getters don't need synchronisation!
return this.ok.get();
}
public String getMessageAndReset() {
// make a copy before resetting the OK
String msgCopy = this.msg;
this.ok.compareAndSet(true, false);
return msgCopy;
}
public void run() {
final Random rand = new Random();
try {
while(true) {
// sleep at random max 5 seconds
// (simulate unpredictable network)
TimeUnit.SECONDS.sleep(rand.nextInt(5));
while(!setMessage("Incoming message")) {
// busy waiting ... waits until the current value has
// been retrieved by the main thread
Thread.sleep(100);
}
}
} catch (Exception e) {
System.out.println(e);
}
}
}
And your main class:
public final class MainClazz implements Runnable {
private final ExecutorService exec;
private final Request request;
public void MainClazz() {
this.exec = new Executors.newFixedThreadPool(4);
this.request = new Request();
this.exec.execute(request);
}
public void run() {
while (true) {
if (request.hasMessage()) {
System.out.println(request.getMessageAndReset());
}
TimeUnit.SECONDS.sleep(10);
}
public static void main(String[] args) {
MainClazz main = new MainClazz();
main.run();
}
}
In this implementation, the Request class only holds a single value at a time. Depending the amount of data you expect you might want to think about using a buffer.
Also, like many others have mentioned, don't use while (true)! Get a synchronisation object from the java concurrent package!
More light reading on the AtomicBoolean object.
I need a little help with java multithread. I have this class:
public class EdgeServer{
private static final int ServidorBordaID = 9;
private static final String urlLogin = "http://localhost/exehdager-teste/index.php/ci_login/logar";
private static final String insertSensorURI = "http://localhost/exehdager-teste/index.php/cadastros/ci_sensor/gravaSensor";
private static final String insertGatewayURI = "http://localhost/exehdager-teste/index.php/cadastros/ci_gateway/gravaGateway";
private static ArrayList<Gateway> gatewaysCadastrados = new ArrayList<>();
public static void main(String[] args) {
// Start a user thread that runs the UPnP stack
Thread clientThread = new Thread(new Descoberta());
clientThread.setDaemon(false);
clientThread.start();
Thread publicationThread = new Thread(new Publication());
publicationThread.setDaemon(false);
publicationThread.start();
}
}
The thread Descoberta will add new itens to gatewaysCadastrados list on demand. and the Publication thread will read this list and execute an action for each object on list.
I just need to know how to share and pass this var to threads. Will I need to build a semaphore to do this?
Here is the sample code where you can share list between two threads and you need to use wait and notify for semaphore.
public class Descoberta extends Thread {
private final ArrayList<Gateway> a = new ArrayList<>();
public Descoberta( ArrayList<Gateway> a) {
this.a = a;
}
#Override
public void run() {
synchronized (a) {
while(true){ // your condition
a.wait();
}
a.notify();
}
}
}
public class Publication extends Thread {
private final ArrayList<Gateway> b = new ArrayList<>();
public Publication(ArrayList<Gateway> b) {
this.b = b;
}
#Override
public void run() {
synchronized (b) {
while(true){ // your condition
b.wait();
}
b.notify();
}
}
}
public class EdgeServer {
public static void main(String args[]) {
private final ArrayList<Gateway> gatewaysCadastrados = new ArrayList<>();
Thread clientThread = new Descoberta(gatewaysCadastrados);
Thread publicationThread = new Publication(gatewaysCadastrados);
clientThread.start();
publicationThread.start();
}
}
A simple way it to pass the shared object as a constructor parameter to the relevant runnables; e.g.
Thread clientThread = new Thread(new Descoberta(gateways));
...
Thread publicationThread = new Thread(new Publication(gateways));
Obviously, the respective Runnable constructors need to save the parameters so that their run() methods can find them.
There are various other ways:
If the runnables are inner classes within the same outer class instance, they can access shared objects in outer class.
If the shared state is stored in static variables, then the runnables can access them via static getters, etcetera. (NOTE: this is most likely bad design ...)
And as #Fidor points out, if two or more threads are going to share a common (mutable) data structure, then they need to synchronize their read and write operations on the data structure. If you neglect this, your application is liable to have the kind of insidious bugs that are hard to reproduce and hard to track down.
I've looked at the java tutorials online and they all seem concerned with catching ActionEvents given out by other components that are already written. Is it possible to write your own objects that have there own set of criteria that trigger actionEvents that can then be caught by other classes that have registered as listeners?
So for example: If I wanted an object that was counting sheep to send out an actionEvent when 100 sheep had been counted to all the sleeper objects that had registered as listeners.
Is there a way to do this are there any tutorials online?
Any help is greatly appreciated.
Yes, it's pretty straightforward, once someone shows you how to create your own listeners.
First, you create your own EventObject. Here's an example from one of my projects.
import gov.bop.rabid.datahandler.bean.InmateDataBean;
import java.util.EventObject;
public class InmatePhotoEventObject extends EventObject {
private static final long serialVersionUID = 1L;
protected InmateDataBean inmate;
public InmatePhotoEventObject(Object source) {
super(source);
}
public InmateDataBean getInmate() {
return inmate;
}
public void setInmate(InmateDataBean inmate) {
this.inmate = inmate;
}
}
There's nothing special about this class, other than it extends EventObject. Your constructor is defined by EventObject, but you can create any methods you want.
Second, you define an EventListener interface.
public interface EventListener {
public void handleEvent(InmatePhotoEventObject eo);
}
You would use the EventObject you created. You can use any method name or names that you want. This is the interface for the code that will be written as a response to the listener.
Third, you write a ListenerHandler. Here's mine from the same project.
import gov.bop.rabid.datahandler.bean.InmateDataBean;
import gov.bop.rabid.datahandler.main.EventListener;
import gov.bop.rabid.datahandler.main.InmatePhotoEventListener;
import gov.bop.rabid.datahandler.main.InmatePhotoEventObject;
import java.util.ArrayList;
import java.util.List;
public class InmatePhotoListenerHandler {
protected List<EventListener> listeners;
public InmatePhotoListenerHandler() {
listeners = new ArrayList<EventListener>();
}
public void addListener(EventListener listener) {
listeners.add(listener);
}
public void removeListener(EventListener listener) {
for (int i = listeners.size() - 1; i >= 0; i--) {
EventListener instance = listeners.get(i);
if (instance.equals(listener)) {
listeners.remove(i);
}
}
}
public void fireEvent(final InmatePhotoEventObject eo,
final InmateDataBean inmate) {
for (int i = 0; i < listeners.size(); i++) {
final EventListener instance = listeners.get(i);
Runnable runnable = new Runnable() {
public void run() {
eo.setInmate(inmate);
instance.handleEvent(eo);
}
};
new Thread(runnable).start();
}
}
public static void main(String[] args) {
System.out.println("This line goes in your DataHandlerMain class "
+ "constructor.");
InmatePhotoListenerHandler handler = new InmatePhotoListenerHandler();
System.out.println("I need you to put the commented method in "
+ "DataHandlerMain so I can use the handler instance.");
// public InmatePhotoListenerHandler getInmatePhotoListenerHandler() {
// return handler;
// }
System.out.println("This line goes in the GUI code.");
handler.addListener(new InmatePhotoEventListener());
System.out.println("Later, when you've received the response from "
+ "the web service...");
InmateDataBean inmate = new InmateDataBean();
inmate.setIntKey(23);
handler.fireEvent(new InmatePhotoEventObject(handler), inmate);
}
}
The main method in this class shows you how you use a ListenerHandler. The rest of the methods in the class are standard. You would use your own EventObject and EventListener.
Yes.
I suggest you look at the java API documentation for ActionEvent and EventListenerList.
I also suggest that you read about the Listener (also called Observer) pattern.
The run method of Runnable has return type void and cannot return a value. I wonder however if there is any workaround of this.
I have a method like this:
public class Endpoint {
public method() {
Runnable runcls = new RunnableClass();
runcls.run()
}
}
The method run is like this:
public class RunnableClass implements Runnable {
public JaxbResponse response;
public void run() {
int id = inputProxy.input(chain);
response = outputProxy.input();
}
}
I want to have access to response variable in method. Is this possible?
Use Callable<V> instead of using Runnable interface.
Example:
public static void main(String args[]) throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(3);
Set<Future<Integer>> set = new HashSet<>();
for (String word : args) {
Callable<Integer> callable = new WordLengthCallable(word);
Future<Integer> future = pool.submit(callable);
set.add(future);
}
int sum = 0;
for (Future<Integer> future : set) {
sum += future.get();
}
System.out.printf("The sum of lengths is %s%n", sum);
System.exit(sum);
}
In this example, you will also need to implement the class WordLengthCallable, which implements the Callable interface.
public void check() {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> result = executor.submit(new Callable<Integer>() {
public Integer call() throws Exception {
return 10;
}
});
try {
int returnValue = result.get();
} catch (Exception exception) {
//handle exception
}
}
Have a look at the Callable class. This is usually submited via an executor service
It can return a future object which is returned when the thread completes
Yes, there are workaround. Just use queue and put into it value which you want to return. And take this value from another thread.
public class RunnableClass implements Runnable{
private final BlockingQueue<jaxbResponse> queue;
public RunnableClass(BlockingQueue<jaxbResponse> queue) {
this.queue = queue;
}
public void run() {
int id;
id =inputProxy.input(chain);
queue.put(outputProxy.input());
}
}
public class Endpoint{
public method_(){
BlockingQueue<jaxbResponse> queue = new LinkedBlockingQueue<>();
RunnableClass runcls = new RunnableClass(queue);
runcls.run()
jaxbResponse response = queue.take(); // waits until takes value from queue
}
}
If you add a field to RunnableClass you can set it in run and read it in method_. However, Runnable is a poor (the Java keyword) interface as it tells you nothing about the (the concept) interface (only useful line of the API docs: "The general contract of the method run is that it may take any action whatsoever."). Much better to use a more meaningful interface (that may return something).
One way is, we have to use Future - Callable approach.
Another way is, Instead of returning value, you can hold in object
Example:
class MainThread {
public void startMyThread() {
Object requiredObject = new Object(); //Map/List/OwnClass
Thread myThread = new Thread(new RunnableObject(requiredObject)).start();
myThread.join();
System.out.println(requiredObject.getRequiredValue());
}
}
class RunnableObject implements Runnable {
private Object requiredObject;
public RunnableObject(Object requiredObject) {
this.requiredObject = requiredObject;
}
public void run() {
requiredObject.setRequiredValue(xxxxx);
}
}
Because object scope is in the same scope so that you can pass object to thread and can retrieve in the main scope. But, most important thing is, we have to use join() method. Because main scope should be waiting for thread completion of its task.
For multiple thread case, you can use List/Map to hold the values from threads.
Try the following
public abstract class ReturnRunnable<T> implements Runnable {
public abstract T runForResult();
#Override
public void run() {
runForResult();
}
}
Take a look at the callable interface, perhaps this suites your needs. You can also try to get the value of the response field by calling a setter-method inside of your run() method
public void run() {
int id;
id =inputProxy.input(chain);
response = outputProxy.input();
OuterClass.setResponseData(response);
}