当前位置: 首页 > 知识库问答 >
问题:

在不使用线程的情况下在Java中实现“Geofence”对象

马承
2023-03-14

我的大学教授给我布置了一个练习,内容如下:

“Geofence对象是一个对象,它有一个对象集合,可以在这些对象发出信号时等待。有一个add(object)方法,它将对象添加到集合中。还有一个await()方法:它允许等待集合中的任何对象发出信号。每当调用add(object)方法时,await()方法处于活动状态时,add的参数将放入队列中。使用以下接口编写源代码:“。

public interface Fence {
    public void await() throws InterruptedException; 
    public void add(Object o); 
}

因此,只有当调用相同数量的notify()和队列中的对象(即add(Object))时,await()终止,队列中的该对象最终被添加到集合中。

我做了如下实现:

import java.util.LinkedList;

public class FenceImpl2 implements Fence{
    
    private LinkedList<Object> collection; 
    private Object mutex; ; 
    static boolean iswaiting = false; 
    
    public FenceImpl2() {
        this.collection = new LinkedList<Object>(); 
        this.mutex = new Object(); 
    }

    @Override
    public void await() throws InterruptedException {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    synchronized(mutex) {   
                    mutex.wait();
                    iswaiting = true; 
                        }
                    } catch (InterruptedException e) {
                            e.printStackTrace();
                        }}}); 
            t1.start(); 
        }

    @Override
    public void add(Object o) {
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized(mutex){
                    if(iswaiting == true) {
                        try {
                            mutex.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } 
                    }
                    else {
                        collection.add(o);
                    }
                }}}); 
        t2.start(); 
    }
    
    public Object getList() throws InterruptedException {
        synchronized(mutex){
            System.out.println("Collection list:  \n"); 
        for(Object o : collection) {
            System.out.println(o); 
            Thread.sleep(1000);
        
        } 
        System.out.println("------- \n"); 
        return collection;
        }
    }
    
    public void notification() {
            Thread thread = new Thread(()->{
                synchronized(mutex){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    mutex.notify();
                    }
                });
            
                thread.start();
    }
    
    
    public static void main(String[] args) throws InterruptedException {
        
        FenceImpl2 f = new FenceImpl2(); 
        Object o1 = 1; 
        Object o2 = 2; 
        Object o3 = 3; 
        Object o4 = 70; 

        f.add(o1);
        System.out.println("Add 1");
        f.add(o2); 
        System.out.println("Add 2");
        f.add(o3);
        System.out.println("Add 3");
        f.await();
        System.out.println("Await active ");
        f.add(o4);
        System.out.println("Aggiungo 70 - Shouldn't appear. Forced in queue");
        f.getList();
        f.notification();
        System.out.println("Notify() sent - 70 should now appear in the collection");
        f.getList();

        
        
    }   
}

在提交给我的教授后,我被告知两件事:

  1. 同步不正确:等待在第一次通知后“解锁”,这不应该发生,因为它不会等待队列中的其他对象(如果有)被通知
    ^让我说,我知道如何轻松解决这个问题,但
  2. 虽然这是一个小错误,但是不应该使用异步专用线程来完成方法等待、添加和通知

我的问题终于来了。如果我没有使用专用线程,我应该如何在一个锁对象上使用wait()然后通知()。我试着移除线程,但是很明显,当我调用mutex.wait()时,程序会锁定,调用通知方法后的代码不会到达。

为什么我的教授告诉我使用线程是错误的?如何在没有程序锁定的情况下使用 wait() 然后在两个单独的方法中调用 notify()?

这是我的意思的一个例子:

public class testw {
    
    private Object mutex; 
    boolean condition = false; 
    
    
    public testw() {
        this.mutex = new Object();
    }
    
    public void startWait() {
        synchronized(mutex) {
            try {
                Thread.sleep(1000);
                condition = true; 
                while(condition == true) {
                    System.out.println("Waiting!");
                    mutex.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }           
        }
    }
    
    public void sendNotify() {
        synchronized(mutex) {
            try {
                Thread.sleep(3000);
                System.out.println("Notify!, not waiting anymore");
                condition = false; 
                mutex.notify();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } 
        }
    }
    
    public static void main(String[] args) {
        
        testw t = new testw(); 
        
        t.startWait();
        t.sendNotify(); 
        
    }

在不使用线程的情况下,当调用startWait()时,主线程进入等待状态,但是无法调用sendNotify()并且程序冻结。有没有一种不使用线程的方法,或者我遗漏了什么?

非常感谢你。

共有1个答案

詹正浩
2023-03-14

我被告知...尽管这是一个小错误,但等待、添加和通知的方法不应使用异步专用线程完成。

名为<code>await()

您的< code>await()方法不会等待。它创建一个新线程,然后立即返回。新线程等待着什么,但之后它就死去了,没有做任何有用的事情。新线程还不如根本不存在。

您的 add(o) 方法也没有多大意义。我甚至不确定你想用它做什么,但我认为你需要退后一步,试着向鸭子解释为什么你认为这两种方法中的任何一个都应该创建一个新的线程。

如果我不使用专用线程,我应该如何在锁对象上使用等待(),然后通知()?

https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

 类似资料:
  • 问题内容: 如果我要使用DefaultServeMux(我将其指定为ListenAndServe的第二个参数来指定),那么我可以访问,您可以在Go Wiki的以下示例中看到该: 在当前代码中,我无法使用DefaultServeMux,即我将自定义处理程序传递给ListenAndServe 因此,我没有内置的代码。但是,我必须将一些授权代码修改为需要类似的授权代码。例如,如果我一直在使用Defaul

  • 问题内容: 我有以下情况。我的工作是: 在给定的时间后可能会超时,如果发生则需要抛出异常 如果没有超时,将返回结果 如果此作业返回结果,则必须尽快将其返回,因为性能非常重要。因此,异步解决方案已经不在市场上了,通过锤子自然捆绑系统也是一种选择。 最后,系统必须符合EJB标准,因此不建议使用普通线程的AFAIK,因为这是严格禁止的。 我们当前的解决方案使用一个线程,该线程在存在一定时间后将被抛出异常

  • 问题内容: 以下App Engine处理程序在可以获取令牌的范围内起作用: 当连接到模板时,它会从Facebook获得令牌响应并愉快地显示它。但是,最好不要将用户重定向到example.com/?state=SOME_UNIQUE_VALUE&code=AQB0iYpAf8nMmX5blahblah# = 来完成登录。 有没有一种方法可以使用client.Get等来访问授权URL,遵循重​​定向,

  • 问题内容: 是否可以在不实现Comparable类的情况下使用Comparator?例如,如果我有以下内容: 然后可以使用comp比较两个对象吗?如果是这样,我将如何去做? 谢谢… 问题答案: 你不用。您使用。 是由对象实现的接口,用于指定它们与相同类型的其他对象的排序顺序。 是一个通用接口,只需要两个对象并告诉您它们的排序顺序。因此,您可以执行以下操作: 与: 和:

  • 问题内容: 我想知道是否有一种方法可以在不使用内置函数的情况下实现SQL分析功能。 问题答案: 这是三个等效的表达式: 假设存在,以使行对于“ row_number”而言是唯一的。

  • 问题内容: 如何在Java程序中打开和关闭调试?如何在不重新编译Java程序的情况下打开和关闭调试? 问题答案: 无需使用IDE进行调试 1)您可以使用Assertions编写Java程序。您随时可以启用/禁用它们。 2)您可以使用配置了log4j.properties的日志。在Java程序中,您可以随时指定信息和调试日志,只要您想显示调试或信息日志等信息,就可以在log4j.properties