Mee*_*ary 6 java static web-applications autocomplete
我的 Web 应用程序的标题中有一个搜索框,并使用自动完成功能来帮助用户按作者姓名或书名查找书籍。根据用户输入,函数通过oninput()调用 servlet 。servlet 调用类的静态方法,该方法返回与输入字符串匹配的书籍数组。FindBooksajaxFindBookssuggest()SuggestionBook
FindBooks.java
JSONArray books = SuggestionBook.suggest(inputString);
out.print(books);
Run Code Online (Sandbox Code Playgroud)
建议书.java
private static boolean isTernaryEmpty = true;
private static Ternary ternary;
private static void fillTernary() {
// fills ternary search tree with data.
isTernaryEmpty = false;
}
public static JSONArray suggest(String searchString) {
if(isTernaryEmpty) {
fillTernary();
}
return ternary.find(searchString);
}
Run Code Online (Sandbox Code Playgroud)
我在类中使用了static方法SuggestionBook.java,以避免为应用程序的每个会话加载数据。因此它只会被加载一次,然后就可以被不同的会话共享。但由于静态方法只有一份副本,并且所有会话都使用相同的static方法来获取数据。当其他会话正在使用该方法时,他们是否必须等待,或者所有会话可以同时访问该方法?如果是,是否会影响应用程序的性能。如果否,JVM 如何管理单个副本的并发访问?最后,根据我的理解,只要类SuggestionBook没有被垃圾收集,数据就会保留在内存中。使用数据结构 as class variablesnot是正确的方法吗instance variables,因为它们会阻塞可用内存更长时间。
当其他会话正在使用该方法时,他们是否必须等待,或者所有会话可以同时访问该方法?
不,他们不必等待,是的,他们可以同时访问。
同时从多个会话访问同一对象可能会出现问题,但不一定是问题。例如,如果两个会话同时访问一个对象而不更改其状态,那就没问题了。如果它们确实改变了状态并且状态转换涉及不稳定的中间状态,则可能会出现问题。
如果两个线程同时运行同一个方法,它们的代码指针都指向该方法,并在堆栈上拥有自己的参数和局部变量副本。只有当它们堆栈上的东西指向堆上的相同对象时,它们才会互相干扰。
如果是,是否会影响应用程序的性能。如果否,JVM 如何管理单个副本的并发访问?
java中的内存分为两种——堆和栈。堆是所有对象所在的地方,而堆栈是线程执行工作的地方。每个线程都有自己的堆栈,并且不能访问彼此的堆栈。每个线程还有一个指向代码的指针,该指针指向它们当前正在运行的代码位。当线程开始运行新方法时,它将该方法中的参数和局部变量保存在自己的堆栈上。其中一些值可能是指向堆上对象的指针。
最后,根据我的理解,只要 SuggestionBook 类没有被垃圾收集,数据就会保留在内存中。使用数据结构作为类变量而不是实例变量是否是正确的方法,因为它们会阻塞可用内存更长的时间。
由于您使用的是 servlet,因此 servlet 的单个实例仅在 web 应用程序启动时创建一次,并在所有请求之间共享。无论是否静态,每个类/实例变量都将在所有请求/会话之间共享。将只有一个 Servlet 实例,并且实例变量将充当静态变量。因此,它不需要通过将变量设为静态而不是实例来要求人们了解单个实例(因为很多人不知道),而是消除了使用中的任何混乱。因此变量的意图更清晰并且不太可能被误解。所以,是的,就可用性而言,这并不是一个坏方法。
小智 0
您可以将 suggest 方法设置为同步,它将起作用。因为只有第一个调用才会将数据填充到树中,而后续调用只会读取它。
但是,如果您同步 suggest 方法,则每个调用 suggest 的线程都将被同步,这是不必要的,因为第一次调用已经填充了树。
解决方案 1) 创建一个静态块并在其中初始化树。这样,一旦加载类,树就会被初始化。
解决方案2)使“fillTernary”方法同步,并且仅当树未初始化时才在方法内部初始化树,即if(isTernaryEmpty)。请注意,这两种方法都需要 if 条件,这是为了防止多个线程同时初始化。