Reputation: 25028
I have a class as such:
import java.util.Vector;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="task-list")
@XmlAccessorType(XmlAccessType.FIELD)
public class TaskList {
@XmlElement(name="task")
Vector<Task> tasks;
public Vector<Task> getTasks(){
return tasks;
}
}
The threads in the GUI manipulate the Vector<Task>
contained within so the operations are synchronized(vectorname){....}
to avoid collisions and inconsistency.
Now, I want to marshall this to an XML file. If I obtain a lock on the TaskList
object while saving (marshalling), will it result in a lock on the Vector
within ?
Basically, the threads can be manipulating the vector when the user presses the save button. I do not want errors to occur and hence the sync block.
Also, I want to avoid deadlocks that may occur if two threads request the same resource at the same time. How can I avoid that ? Is setting the priority a good choice ?
package jaxb.classes;
import javax.xml.bind.annotation.*;
import java.util.Vector;
import java.io.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class Task {
@XmlElement(name="input")
private String input; // String representing the input file
@XmlElement(name="output")
private String output; // String representing the output file
@XmlElement(name="format")
private Format format; // a jaxb.classes.Format representing the format of conversion
@XmlElement(name="taskID")
private long taskID; // a unique ID for each task.
@XmlElement(name="isReady")
public boolean isReady; // boolean value representing whether the task is ready for conversion
@XmlTransient
public boolean isChanging = false; // boolean representing if the user is changing the task DO NOT MARSHALL
@XmlTransient
public boolean isExecuting = false; // boolean representing whether the task is being executed DO NOT MARSHALL
public long getTaskID(){
return taskID;
}
public String getInput(){
return input;
}
public String getOutput(){
return output;
}
public Format getFormat(){
return format;
}
public void setOutput(String out){
output = out;
}
public void setFormat(Format f){
format = f;
}
/*
* This method will be used to create a vector
* which will be used to add row representation
* of the ask.
*/
public Vector<Object> getRowForm(){
Vector<Object> rowForm = new Vector<Object>();
rowForm.add(input);
rowForm.add(output);
rowForm.add(format.toString());
File f = new File(input);
double d = (double) (f.length()/(1024*1024));
String fileSize = String.format("%7.2f MB",d);
rowForm.add(fileSize);
return rowForm;
}
/*
* This is the only constructor that will be called
* when the user drops new file(s).
* This will be called in the AddNewTaskWindow class.
* {@param i} is a String representing input file
* {@param o} is a String representing output location
* {@param f} is a jaxb.classes.Format representing the format to convert to
* {@param taskID} is a unique ID for the task.
*/
public Task(String i, String o,Format f, long taskID){
input = i;
output = o;
format = f;
this.taskID = taskID;
}
}
Upvotes: 1
Views: 722
Reputation: 4507
As you aware the methods in Vector
class is synchronized so any access to vector instance will be safe. However are the task instances in the vector thread-safe ? otherwise you will not be able to protect them from concurrent access as you described. My suggestion is not to use this blocking approach and avoid using shared task list to perform this operation, Use asynchronous event driven approach. Because updating those tasks in GUI threads and JAXB
operations are two different operations/behaviours of your program. you can manipulate tasks in GUI related threads and fire events using an executor or eventbus when you need to save (or any other non-ui related work). Then you can have another thread to do JAXB
operations, another advantage is you can get the callbacks events once you complete the save which you can listen from the UI threads. So you don't have to worry about any maintaining shared resources or synchronization of them and will be easy to maintain.
Upvotes: 2