I'm getting into java multithreading, and decided to solve a more complex problem, but with little success so far.
I have a production line of workers that will try to get work (create a product) from a list:
- i'm using executors to generate the worker threads;
- each product creation implies the completion of a set of Tasks;
- each Task has an associated time an resources it needs: exclusive access to each resource is needed, meaning it is impossible to use one in the creation of two products simultaneously.
The concurrent access to the work list was solved with notify-wait:
public class ProductionRequestQueue extends LinkedList<ProductionRequest> {
public ProductionRequestQueue() {
}
public synchronized void push(ProductionRequest productionRequest) {
this.add(productionRequest);
notifyAll();
}
public synchronized ProductionRequest pull() {
while (this.size() == 0) {
try {
wait();
} catch (InterruptedException e) {
}
}
return this.removeFirst();
}}
The problem is when i need to guarantee exclusive access to the resources. I have a list of the available resources in the production line, but i need to guarantee access to the resource it self and not the list. My workers does:
public Product createProduct(ProductionRequest productionRequest) {
Product product = ProductionLine.products.get(productionRequest.getProductId());
product.create();
return product;
}
@Override
public void run() {
ProductionRequest productionRequest;
while (!productionRequestQueue.isEmpty()) {
productionRequest = productionRequestQueue.pull();
createProduct(productionRequest);
System.out.println(productionRequest + " is being manufactured by " + this);
}
}
Then i have a class that relates the resource with the time, where it simulates the production process by sleeping the thread:
public ResourceTime(Resource resource, int time) {
this.resource = resource;
this.time = time;
}
public void execute() {
synchronized (this.resource) {
Thread thread = new Thread(this);
thread.start();
}
}
@Override
public void run() {
try {
System.out.println(toString());
Thread.sleep(Integer.valueOf(time));
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
I thought that the syncronized block would guarantee exclusive access to the resource, but i keep getting a null pointer exception:
Exception in thread "pool-1-thread-2" java.lang.NullPointerException
at production_line_sim.models.Worker.createProduct(Worker.java:14)
Any thoughts about this?
Also, how can i demonstrate that the synchronized block guarantees exclusive access to each resource? I think this solution may lead to a situation where some threads may not be able to access the resource, and some kind of fairness algorithm might be needed, can someone pinpoint me on how to do this?