如何避免多线程处理同一个对象JAVA

时间:2018-04-22 04:05:26

标签: java multithreading synchronization polling

我的多线程有问题,链接列表 poll(),而offer()返回null,因为它已经确保它不是空的 wait()并通知(),为了更清楚,我遇到与this guy类似的问题。

解决方案:

根据this guy,他通过以下方式解决问题:

  

这里的问题是我使用2个线程来处理队列,不应该使用   正常队列。如有任何问题我会反馈

意味着他在同一个对象上使用2个线程,这意味着两个线程都希望执行这些作业会导致两者都无法执行,因为它返回null 。要解决它,你只需要运行一个线程或同步?如上所述:

  

只要您对其进行同步或拍摄,就可以使用“普通队列”   确保线程安全的其他措施

我的问题

我仍然希望有多个线程处理同一个对象,但是同步和锁定。完成后,它仍然显示与锁定后之前相同的问题

有问题的代码

导致问题的代码,也许我的锁实现是错误的,所以它不会工作?我会一步一步解释:

public void CleanBus(String CleanerName) {
    Bus bus;
    Boolean BusClean = false;
    synchronized (ListBusEngineFix) {
        while (ListBusEngineFix.size() == 0) {
            try {
                ListBusEngineFix.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

上面的代码用于确保List MUST NOT EMPTY ,如果它传递了此代码意味着ListBusEngineFix不为空,并且可以在此之后进行轮询。

确保列表不为空后,我会尝试轮询,并将其存储在另一个列表中

        bus = (Bus) ((LinkedList<?>) ListBusEngineFix).poll();
        try {
            Thread.sleep(200);
            System.out.println("Cleaners: " + CleanerName + "cleaning " + bus.getBusName());
            BusClean = new Random().nextBoolean();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        ((LinkedList<Bus>) ListBusClean).offer(bus);

    }

如此处所示,我仍在同步方法中,我尝试轮询并且延迟200ms ,然后开始打印轮询值的值。

结果

Exception in thread "Thread-4" java.lang.NullPointerException
    at BusShop.CleanBus(BusShop.java:130)
    at Cleaner.CleanBus(Cleaner.java:25)
    at Cleaner.run(Cleaner.java:13)
    at java.lang.Thread.run(Thread.java:748)

Exception in thread "Thread-3" java.lang.NullPointerException
    at BusShop.CleanBus(BusShop.java:130)
    at Cleaner.CleanBus(Cleaner.java:25)
    at Cleaner.run(Cleaner.java:13)
    at java.lang.Thread.run(Thread.java:748)

正如看到的结果,我们已经知道两个线程在仍处于同步锁定时想要访问

附加代码

这是使线程能够更早地运行CleanBus函数的代码。

@Override
public void run() {
    CleanBus();
}

private void CleanBus() {
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    while (true) {
        synchronized(this) {
            busShop.CleanBus(CleanerName);
            notify();
        }

    }
}

对于Main我创建2个线程,如下所示,没有问题。

    Cleaner cleaner = new Cleaner(busShop, "Cleaner 1");
    Cleaner cleaner2 = new Cleaner(busShop, "Cleaner 2");

    Thread thCleaner = new Thread(cleaner);
    Thread thCleaner2 = new Thread(cleaner2);

    thCleaner.start();
    thCleaner2.start();

notify()来自哪里唤醒 wait()

    //Unshown code are poll offer, so that ListBusEngineFix notify, basically it will not empty.
    if (ListBusEngineFix.size() != 0) {
        synchronized (ListBusEngineFix) {
            ListBusEngineFix.notify();
        }
    }

HINT

这并不是每次都显示,大约10次尝试,有2次空例外,有时甚至更糟。原因可能是其他线程忙,所以只有一个访问它,并且没有问题。

好的,我的同步无法为一个线程锁定一个对象是否存在问题?

0 个答案:

没有答案