有没有办法避免在不使用静态或单例的情况下覆盖新数据? [英] Is there a way to avoid overwriting new data without using statics or singletons?

查看:53
本文介绍了有没有办法避免在不使用静态或单例的情况下覆盖新数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几个场景。

如果两个单独的类几乎同时从同一个文件接收相同的数据,则更改数据。



场景1:

类1从调用类传递数据。

类2从同一个调用类传递相同的数据。

两个类都会更改数据并将其返回到调用类。



场景2:

类1和2加载大约在同一时间的数据。

1级保存,然后2级保存。



避免这些情况的最佳方法是什么?



我尝试过的事情:



创建一个神级处理所有数据加载,更改和保存。不是最好的方法,并试图找到更好的方法。

解决方案

我想到的第一件事是互斥。既然你在谈论Java编程,我将仅限于Java环境。



Mutex用于多线程环境,其中多个线程将对同一主题执行操作。这样,一个更简单的解决方案可能是这样的,

  //  保存标志 
public static boolean writing = false;
public void write(BufferedWriter bw){
if (!writing){ // 或者您可能想要使用循环等待该线程。
synchronized (bw){
writing = true;
// 将数据写入文件
}
写作= false;
}
}



这样,您将只有一个对象将数据写入文件。但是,这会导致以后的线程等待。我写的一个示例程序只是为了澄清你将如何做到这一点就是这样,



  //  用户对象 
public class 用户{
public String name;
public int age;

public void write( int name){
System.out.println( String .valueOf(name)+ 输入的线程。);
new Writer()。write( this .name + + String .valueOf(age),name);
System.out.println( String .valueOf(name)+ 线程离开。);
}
}

// Writer对象;你可以创建一个保存线程的函数
// 我暂停了线程而不是执行写作的任务。
public class Writer extends OutputStream {

public void write(字符串数据, int 数字){
尝试 {
写(数字);
} catch (IOException ex){
Logger.getLogger(Writer。 class .getName())。log(Level.SEVERE,null,ex);
}
}

@覆盖
public void write( int b) throws IOException {
synchronized this ){
try {
Thread.sleep( 2000 );
} catch (InterruptedException ex){
Logger.getLogger(Writer。 class .getName())。log(Level.SEVERE,null,ex);
}
}
}
}

// 调用函数,
public static void main( String [] args){
User u1 = 用户();
用户u2 = 用户();

u1.name = Afzaal Ahmad Zeeshan;
u2.name = Afzaal Ahmad Zeeshan;
u1.age = 20 ;
u1.age = 20 ;

u1.write( 1 );
u2.write( 2 );
}



一旦这个程序生成输出就像这样,



输入1个主题。 
1离线。输入
2个主题。
2离线。
// BUILD SUCCESSFUL(总时间:4秒)



花了4秒钟,因为每个线程耗时2秒,直到发生这种情况,其他线程不被允许对该对象执行任何操作。看一下, synchronized(this)将对象引用保存到自身。



多线程 - 什么是互斥? - 堆栈溢出 [ ^ ]

https://docs.oracle.com/javase/tutorial /essential/concurrency/sync.html [ ^ ]

课程:并发(Java& amp; ;交易;教程>基本类) [ ^ ]


问题与静态成员或单例模式的概念无关。问题是多线程问题,共享数据,更准确地说,是对共享对象的访问,并通过互斥来解决。您必须了解线程同步的本质:

相互排斥 - 维基百科,免费的百科全书 [ ^ ],

重要部分 - 维基百科,免费的百科全书 [ ^ ],

同步(计算机科学) - 维基百科,免费的百科全书 [ ^ ],

竞争条件 - 维基百科,免费的百科全书 [< a href =https://en.wikipedia.org/wiki/Race_conditiontarget =_ blanktitle =新窗口> ^ ]。



解决方案1为您提供互斥锁使用示例。



但是你的困惑源于对你正在做的事情缺乏清楚的理解。首先,您总是谈论一个或另一个类对数据执行一个或另一个操作。这里的课程基本上无关紧要;你应该想到类,对象的实例。如果两个实例同时处理相同(共享)对象,则它们是相同类还是不同类并不重要。但是,你根本没有提到线程,所以不清楚你是否甚至面对线程同步问题。现在还不是很清楚大致相同可能意味着什么,但假设你真的并行做某事会更安全。



另一个问题是:你混淆了静态成员和带有共享数据的单例。



如果对象是共享的,那么它是否是某个类的静态成员并不重要。同样,单个模式是否实现并不重要。您只需在代码的不同部分共享对同一对象的引用;这一切都很重要。实际上,通过各种方式避免静态数据非常重要;最好也避免使用单例,这是更好的。



即使没有静态也没有单例,可以实现对象的共享,这是必需的,包括案例什么时候它应该只是应用程序运行时中的一个;您达到与使用此对象相关的所有相同目标,并在同时使用它时遇到相同的同步问题。想象一下场景:在执行堆栈的上部某处,您创建了访问数据的两个对象,数据类并将数据类的引用传递给两个对象。当您需要互斥锁时,您还可以在此代码中创建它并将引用传递给相同的对象。这就是全部。



最后,让我注意到上帝对象甚至不是一种模式。这是一个坏事,一个众所周知的面向对象编程的反模式。请参阅:

上帝对象 - 维基百科,免费的百科全书 [ ^ ],

反模式 - 维基百科,免费的百科全书 [ ^ ]。



-SA

Couple of scenarios.
If 2 separate classes receive the same data from the same file at about the same time, then change the data.

Scenario 1:
Class 1 is passed the data from an invoking class.
Class 2 is passed the same data from the same invoking class.
Both classes change the data and return it to the invoking class.

Scenario 2:
Classes 1 and 2 load the data at about the same time.
Class 1 saves, then class 2 saves.

What is the best way to avoid these situations?

What I have tried:

Created a god class to handle all the data loading, changing and saving. Not the best method and trying to find a better way.

解决方案

The first thing that I came to think of was a mutex. Since you are talking about Java programming I will restrict myself to Java environment only.

Mutex are used in multithreading environments where multiple threads are going to perform actions on the same topic. This way, a simpler solution may be like this,

// Save a flag
public static boolean writing = false;
public void write(BufferedWriter bw) {
   if(!writing) { // Or you may want to use a loop to wait for that thread.
      synchronized(bw) {
         writing = true;
         // Write the data to the file
      }
      writing = false;
   }
}


This way, you will have just one single object writing the data out to the file at the time. However, this would cause later threads to wait. An example program that I wrote just to clarify how you will be doing this is like this,

// User object
public class User {
    public String name;
    public int age;
    
    public void write(int name) {
        System.out.println(String.valueOf(name) + " thread entered.");
        new Writer().write(this.name + ", " + String.valueOf(age), name);
        System.out.println(String.valueOf(name) + " thread leaving.");
    }
}

// Writer object; you can create a function that holds the thread
// I paused the thread instead of performing the task of writing. 
public class Writer extends OutputStream {
    
    public void write(String data, int number) {
        try {
            write(number);
        } catch (IOException ex) {
            Logger.getLogger(Writer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void write(int b) throws IOException {
        synchronized(this) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                Logger.getLogger(Writer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

// Calling the functions, 
public static void main(String[] args) {
        User u1 = new User();
        User u2 = new User();
        
        u1.name = "Afzaal Ahmad Zeeshan";
        u2.name = "Afzaal Ahmad Zeeshan";
        u1.age = 20;
        u1.age = 20;
        
        u1.write(1);
        u2.write(2);
    }


Once this program generates the output it is like this,

1 thread entered.
1 thread leaving.
2 thread entered.
2 thread leaving.
// BUILD SUCCESSFUL (total time: 4 seconds)


It took 4 seconds because each thread took 2 seconds and until that was happening other threads were not allowed to perform anything on that object. Have a look at that, "synchronized (this)" which hold the object reference to itself.

multithreading - What is a mutex? - Stack Overflow[^]
https://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html[^]
Lesson: Concurrency (The Java&trade; Tutorials &gt; Essential Classes)[^]


The problem is unrelated to the concept of static member or singleton pattern. The problem is the problem of multithreading, the shared data, more exactly, access to the shared objects, and is solved via the mutual exclusion. You have to understand the essence of thread synchronization:
Mutual exclusion — Wikipedia, the free encyclopedia[^],
Critical section — Wikipedia, the free encyclopedia[^],
Synchronization (computer science) — Wikipedia, the free encyclopedia[^],
Race condition — Wikipedia, the free encyclopedia[^].

Solution 1 gives you an example of mutex use.

But your confusion stems from the lack of clear understanding what you are doing. First of all, you always talk about one or another class performing one or another action on the data. Classes are essentially irrelevant here; you should think of instances of classes, objects. If two instances work on the same (shared) objects concurrently, it does not matter if they are of the same class or different classes. However, you didn't mention the threads at all, so it's not clear if you even face the thread synchronization issues at all or not. It's not really clear what "about the same" may possibly mean, but it would be safer to assume you really do something in parallel.

Another problem is: you confuse static members and singletons with shared data.

If the object is shared, it does not matter if it is static member of some class or not. Likewise, it does not matter if singleton pattern is implemented or not. You simply share the reference to the same object in different parts of the code; this is all that matters. Actually, it's important to avoid static data by all means; and singleton, which is better, is also best avoided.

Even without static and without singleton, sharing of objects can be implemented, it this is needed, including the cases when it should be only one in the application runtime; you reach all the same goals related to the use of this object and face the same synchronization problems in case of concurrent use of it. Imagine the scenario: somewhere on the upper place of the execution stack, you create both objects accessing the data, the data class and pass the reference of the data class to both objects. As you need the mutex, you also create it in this code and pass the reference to the same objects. That's all.

And finally, let me note that "god object" is not even a pattern. It's a bad thing, a well-known anti-pattern of object-oriented programming. Please see:
God object — Wikipedia, the free encyclopedia[^],
Anti-pattern — Wikipedia, the free encyclopedia[^].

—SA


这篇关于有没有办法避免在不使用静态或单例的情况下覆盖新数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆