synchronizing only the assigning of a static variable - static

I have a static variable which will be fetched a lot. I want to synchronize the initialization, but want it to be lazy loaded. So not making it final.
Is this a correct/acceptable approach ?
Here is the code.
public class Test {
private static Object staticObj;
public static Object getStaticObj() throws Exception{
if(staticObj == null){
assignNewStaticObj();
}
return staticObj;
}
private static void assignNewStaticObj(){
synchronized(staticObj){
if (staticObj == null) {
staticObj = new Object();
}
}
}
}

You can synchronize on something else that is static, cheap and not lazy:
public class Test {
...
private static Object staticObjSync = new Object();
...
private static void assignNewStaticObj() {
synchronized(staticObjSync) {
...

Related

Save List of PropertyBusinessObjects to the Storage

I need to save a dinamic List of PropertyBusinessObjects to the Storage, but I didn't find how to do that. I should be able to add and remove items from the list.
The following test code throws java.io.IOException: Object type not supported: CollectiveDAO. I use registerExternalizable().
public class TestSaveListDAOs {
private Form current;
private Resources theme;
public static List<CollectiveDAO> collectivesDB = new ArrayList<>();
public void init(Object context) {
[...]
}
public void start() {
if(current != null){
current.show();
return;
}
Form hi = new Form("Hi World", BoxLayout.y());
hi.add(new Label("Hi World"));
hi.show();
restoreDB();
collectivesDB.add(new CollectiveDAO());
collectivesDB.add(new CollectiveDAO());
saveDB();
restoreDB();
}
public void stop() {
[...]
}
public void destroy() {
}
public static void saveDB() {
for (CollectiveDAO collectiveDAO : collectivesDB) {
collectiveDAO.getPropertyIndex().registerExternalizable();
}
Storage.getInstance().writeObject("CollectivesDB", collectivesDB);
}
private static void restoreDB() {
Object restoredCollectivesDB = Storage.getInstance().readObject("CollectivesDB");
if (restoredCollectivesDB != null) {
collectivesDB = ((List) restoredCollectivesDB);
}
}
}
public class CollectiveDAO implements PropertyBusinessObject {
public final Property<String, CollectiveDAO> collectiveID = new Property<>("collectiveID");
private final PropertyIndex idx = new PropertyIndex(this, "CollectiveDAO",
collectiveID);
#Override
public PropertyIndex getPropertyIndex() {
return idx;
}
}
I'd use JSON rather than Externalizable such as:
public static void saveDB() {
PropertyIndex.storeJSONList("CollectivesDB", collectivesDB);
}
private static void restoreDB() {
collectivesDB = new CollectiveDAO().getPropertyIndex().loadJSONList("CollectivesDB");
}
It's shorter with nicer output. However, if you want to use Externalizable your usage is incorrect. You should remove the for call and instead do:
public void init(Object context) {
new CollectiveDAO().getPropertyIndex().registerExternalizable();
[...]
}
This is needed only once for reading and writing (it was missing for reading). As it registers the new object type (CollectiveDAO).

My application usage memory remained high even after clear all my objects list

So i have this Base Class:
public abstract class WiresharkFile : IDisposable
{
private string _fileName;
private int _packets;
private int _packetsSent;
private string _duration;
private double _speed;
private int _progress;
protected abstract WiresharkFilePacket ReadPacket();
public abstract IEnumerator<WiresharkFilePacket> GetEnumerator();
public abstract void Rewind();
public string FileName
{
get { return _fileName; }
set { _fileName = value; }
}
public int Packets
{
get { return _packets; }
set { _packets = value; }
}
public void Dispose()
{
// implemented inside sub class.
}
}
And specific Wireshark format (libpcap):
public class Libpcap : WiresharkFile, IDisposable, IEnumerable<WiresharkFilePacket>
{
private BinaryReader binaryReader;
private Version version;
private uint snaplen;
private int thiszone;
private uint sigfigs;
private LibpcapLinkType linktype;
private long basePos;
private bool byteSwap;
private static uint MAGIC = 0xa1b2c3d4;
private static uint MAGIC_ENDIAN = 0xd4c3b2a1;
public Libpcap(string path)
: this(new FileStream(path, FileMode.Open, FileAccess.Read))
{
FileName = path;
}
private Libpcap(Stream fileStream)
{
...
}
public override void Rewind()
{
binaryReader = new BinaryReader(new FileStream(FileName, FileMode.Open, FileAccess.Read));
binaryReader.BaseStream.Position = basePos;
}
public void Dispose()
{
if (binaryReader != null)
binaryReader.Close();
}
I removed almost all parts of how i am read this file
Add files in to my application
I have this objects list:
public ObservableCollection<WiresharkFile> wiresharkFiles { get; set; }
This list is binding into my ListView.
When the user choose files to add into my application:
string[] files = openFileDialog.FileNames;
I am check this files via another class:
public class FileValidation
{
public static void DoWork(IEnumerable<string> files)
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
Task task = Task.Factory.StartNew(() =>
{
try
{
Parallel.ForEach(files,
new ParallelOptions
{
MaxDegreeOfParallelism = 3
},
file =>
{
ProcessFile(file);
});
}
catch (Exception)
{ }
}, tokenSource.Token,
TaskCreationOptions.None,
TaskScheduler.Default).ContinueWith
(t =>
{
if (FinishValidationEventHandler != null)
FinishValidationEventHandler();
}
, TaskScheduler.FromCurrentSynchronizationContext()
);
}
private static void ProcessFile(string file)
{
ReadWiresharkFormat(file);
using (WiresharkFile wiresharkFile = new Libpcap(file))
{
WiresharkFileInfo.ReadInfo(wiresharkFile);
// Add file into my list.
}
}
private static WiresharkFileFormat ReadWiresharkFormat(string file)
{
using (BinaryReader binaryReader = new BinaryReader(File.Open(file, FileMode.Open, FileAccess.Read)))
{
// Open file and read first 4 bytes in order to verify file type.
}
}
private static void ReadInfo(WiresharkFile wiresharkFile)
{
foreach (WiresharkFilePacket packet in wiresharkFile)
{
// Collect file information (number of packets...)
}
}
}
OK so until here all good.
Now when add many files, lets say (1000+-) i can see that my memory usage is growing in 200MB but after clear this list the memory usage not changed.
Any idea what could cause this ?

Populate my ListView with item source from class

I have this Singleton that hold my ObservableCollection<MyData> as a memeber:
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
public ObservableCollection<MyData> Files { get; private set; }
private Singleton()
{
Files = new ObservableCollection<MyData>();
}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
Declaration from main form class:
ObservableCollection<MyData> Files;
And here after the constructor:
Files= Singleton.Instance.Files;
XAML:
<ListView ItemsSource="{Binding Files}" />
Now when the user choose files i want to check each file:
private static void Check(IEnumerable<string> files)
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
Task task = Task.Factory.StartNew(() =>
{
try
{
Parallel.ForEach(files,
new ParallelOptions
{
MaxDegreeOfParallelism = 1
},
file =>
{
ProcessFile(file);
});
}
catch (Exception)
{ }
}, tokenSource.Token,
TaskCreationOptions.None,
TaskScheduler.Default).ContinueWith
(t =>
{
}
, TaskScheduler.FromCurrentSynchronizationContext()
);
}
And:
private static void ProcessFile(string file)
{
// Lets assume that i want to add this file into my `ListView`
MyData data = new .....
Singleton.Instance.Files.Add(data);
}
So after this point when i am add files into my list nothing happenning.
Using your code above i was able to reproduce the issue you describe.
The problem is that WPF cannot bind to fields, see this question for more details. All you need to do is to change the ObservableCollection<MyData> in the code behind of your main form to a property instead of a field.
public partial class MainWindow : Window
{
public ObservableCollection<MyData> Files { get; private set; }

How to use different behaviours in the same ViewModel?

I have the view designed for the long running tasks. It has a header and a progress bar.
So the model has the text for a header and a counter for a progress bar and a TotalAmountOfWork field. The model also has
public delegate void TaskCompleted(string resultDescription);
public event TaskCompletedCopyingCompletedEvent;
public event Action UpdateViewState;
When counters change the model invokes UpdateViewState.
ViewModel is subscribed for the events and updates in it's turn the view.
Ok. I have two classes intended to copy files from a hard disk to a flash drive and one class intended for diagnostic information retrieving and this information should be copied to a flash drive finally too.
I want to use them in the same ViewModel, but I can't figure out how to avoid code repeating. I can't figure out how to make it relying on the proper object oriented design.
Those three classes could implement an interface like this:
interface ILongRunningTask {
void DoWork();
}
And then I can implement ViewModel taking ILongRunningTask as an argument.
But look at the name of the name of the interface. It looks too generalized. It seems that something wrong with such an abstraction.
Ok. It seems to me that ViewModel should take a delegate in order to invoke a long running task. But in this case how the ViewModel will interact with the model updating it's properties?
//update
Now, model looks like:
public class FilesCopyingModel : IFilesCopier {
protected int filesCountToCopy;
public int FilesCountToCopy {
get { return filesCountToCopy; }
set {
filesCountToCopy = value;
InvokeUpdateViewState();
}
}
protected int currentProgressValue;
public int CurrentProgressValue {
get { return currentProgressValue; }
set {
currentProgressValue = value;
InvokeUpdateViewState();
}
}
public delegate void CopyingCompleted(string resultDescription);
public event CopyingCompleted CopyingCompletedEvent;
public event Action UpdateViewState;
private readonly IFilesCopier filesCopier;
protected FilesCopyingModel() {
}
public FilesCopyingModel(IFilesCopier filesCopier) {
if (filesCopier == null)
throw new ArgumentNullException("filesCopier");
this.filesCopier = filesCopier;
}
protected static string GetCurrentDateTime() {
return DateTime.Now.ToString("dd.MM.yyyy hh.mm.ss");
}
protected void InvokeCopyCompletedEvent(string resultDescription) {
if (CopyingCompletedEvent != null)
CopyingCompletedEvent(resultDescription);
}
protected void InvokeUpdateViewState() {
if (UpdateViewState != null)
UpdateViewState();
}
protected DriveInfo GetFirstReadyRemovableDrive() {
return
DriveInfo.GetDrives()
.FirstOrDefault(driveInfo => driveInfo.DriveType == DriveType.Removable && driveInfo.IsReady);
}
public void Copy() {
filesCopier.Copy();
}
}
public interface IFilesCopier {
void Copy();
}
public class KFilesCopier : FilesCopyingModel, IFilesCopier {
private string destinationKFilesDirPath;
public new void Copy() {
//some code
}
private static string ComposeDestinationKFilesDirPath(DriveInfo drive) {
//some code
}
}
public class LogsDirCopier : FilesCopyingModel, IFilesCopier {
public readonly string LogsDirPath;
public LogsDirCopier() {
//some code
}
public new void Copy() {
//some code
}
private void InternalCopyLogsDir(string destinationPath) {
//some code
}
private static void CloseStorer(ZipStorer zipStorer) {
//some code
}
private static string ComposeDestinationArchiveFilePath(string destinationPath) {
//some code
}
private void DetermineLogFilesCount() {
//some code
}
ViewModel interact with infrastructure above like this:
public class FilesCopyingViewModel: Screen {
private readonly FilesCopyingModel model;
private readonly IWindowManager windowManager;
public int CurrentProgress {
get { return model.CurrentProgressValue; }
}
public int FilesCountToCopy {
get { return model.FilesCountToCopy; }
}
[ImportingConstructor]
public LongRunningViewModel(IFilesCopier copier) {
model = copier as FilesCopyingModel;
model.CopyingCompletedEvent += CopyingCompletedHandler;
model.UpdateViewState += UpdateViewStateHandler;
windowManager = new WindowManager();
}
private void UpdateViewStateHandler() {
NotifyOfPropertyChange(() => CurrentProgress);
NotifyOfPropertyChange(() => FilesCountToCopy);
}
private void CopyingCompletedHandler(string resultDescription) {
//some code
}
private void RemoveDriveSafely() {
//some code
}
private void PromptEjection(string result) {
//some code
}
private void PromptSuccessEjection() {
//some code
}
private void PromptEjectFlashError() {
//some code
}
protected override void OnActivate() {
try {
var copier = (IFilesCopier) model;
Task.Factory.StartNew(copier.Copy);
}
catch (Exception ex) {
//error handling
}
}
}
These two classes use "Copy" as the name of the method. Now I want to add one more class with very similar behavior, but it seems that it's method should be named like "CollectDiagnosticInfo". Or maybe I can add a class DiagnosticInfoCopier:IFilesCopier and then just do the same. I really don't know, but the sixth sense suggests that there is a smell of some kind.

Java: how to "restart" a static class?

I have a static class (Foo) and a main class (Main)
See Main.java:
public class Main {
public static void main(String[] args) {
System.out.println(Foo.i); // 0
Foo.i++;
System.out.println(Foo.i); // 1
// restart Foo here
System.out.println(Foo.i); // 1 again...I need 0
}
}
See Foo.java:
public class Foo {
public static int i = 0;
}
Is there any way to restart or reset a static class?
Note: I need this because I'm testing a static class with jUnit and I need to clean parameters before second test.
EDIT
ALMOST SOLUTION:
Using StanMax answer, I can to this:
Main.java
public class Main {
public static void main(String[] args) throws Exception {
test();
test();
}
public static void test() throws Exception {
System.out.println("\ntest()");
MyClassLoader myClassLoader = new MyClassLoader();
Class<?> fooClass = myClassLoader.loadClass(Foo.class.getCanonicalName());
Object foo = fooClass.newInstance();
System.out.println("Checking classloader: " + foo.getClass().getClassLoader());
System.out.println("GC called!");
System.gc();
}
}
MyClassLoader.java
public class MyClassLoader {
private URLClassLoader urlClassLoader;
public MyClassLoader() {
try {
URL url = new File(System.getProperty("user.dir") + "/bin/").toURL();
URL[] urlArray = {url};
urlClassLoader = new URLClassLoader(urlArray, null);
} catch (Exception e) {
}
}
public Class<?> loadClass(String name) {
try {
return (Class<?>) urlClassLoader.loadClass(name);
} catch (Exception e) {
}
return null;
}
#Override
protected void finalize() throws Throwable {
System.out.println("MyClassLoader - End.");
}
}
Foo.java
public class Foo {
public static int i = 0;
static {
System.out.println("Foo - BEGIN ---------------------------------");
}
public void finalize() throws Throwable {
System.out.println("Foo - End.");
}
}
OUTPUT
test()
Foo - BEGIN ---------------------------------
Checking classloader: java.net.URLClassLoader#ec160c9
GC called!
MyClassLoader - End.
Foo - End.
test()
Foo - BEGIN ---------------------------------
Checking classloader: java.net.URLClassLoader#ec3fb9b
GC called!
MyClassLoader - End.
Foo - End.
PROBLEM: if I do the cast bellow:
Foo foo = (Foo) fooClass.newInstance();
I get error:
java.lang.ClassCastException
Only if you can unload class, get it re-loaded, as class static code gets executed when class is loaded.
But you can just directly modify the value:
Foo.i = 0;
(or create equivalent method for doing it, esp. if static member is not public)
Create a static method that sets the class variables to their initial values, then call it when you need it.
Avoid static.
It is well known that static is not testable and should thus be avoided. For example, avoiding static is one of the key motivations behind dependency injection. If you need one instance only at runtime, use the singleton pattern instead. And create a new instance for each test run.
You can try this.
Main MainObject = new Main;
MainObject.main(args);
It will restart the class again and again until you stop the class.

Resources