简体   繁体   English

Java并发:一些帮助

[英]Java concurrency: some assistance

I have a class like this: 我有这样的课:

package crossRoadConcurency;

import java.util.List;

public class TourGuide 
{
    private volatile boolean isGuiding;
    private volatile boolean isInShop;
    private final Object lockObject = new Object();
    private final int id;

    public TourGuide(int id)
    {
        this.isGuiding=false;
        this.isInShop=false;
        this.id=id;
    }

    public synchronized boolean isFree()
    {
        return !isGuiding && !isInShop;
    }

    public void guide(final Tourist[] tourists)
{
    new Thread(new Runnable() 
    {   
        @Override
        public void run() 
        {
            synchronized (lockObject) 
            {
                while(!isFree()) 
                {
                    try 
                    {
                        System.out.println("Guide "+id+" is bussy. Waiting... ");
                        lockObject.wait();
                    } 
                    catch (InterruptedException e) 
                    {
                        e.printStackTrace();
                    }
                }
            }
            isGuiding=true;
            System.out.println("Guide "+id+" is guiding "+tourists.length+" tourists");
            try 
            {
                Thread.sleep(4000);//lets not wait one hour, shall we?
                for (Tourist tourist : tourists) 
                {
                    tourist.exit();
                }
                System.out.println("All tourists exited for guide "+id+". Going to shop");
                isInShop=true;
                isGuiding=false;//if we invert the way we give these values bad thing may happen
                Thread.sleep(4000);
                isInShop=false;
                System.out.println("Guide "+id+" is free");
                synchronized (lockObject) 
                {
                    lockObject.notifyAll();
                }
            } 
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }   

        }
    }).start();
}
}

And another class: 还有另一类:

package crossRoadConcurency;

import java.util.Random;

public class Tourist 
{
    public void exit() throws InterruptedException
    {
        Random random = new Random();
        Thread.sleep(random.nextInt(1000));// max one second to exit
    }
}

Which I use like this: 我这样使用:

package crossRoadConcurency;

import java.util.List;

public class Main 
{

    public static void main(String[] args) throws InterruptedException
    {
        Tourist[] tourists = new Tourist[20];
        for (int i=0;i<tourists.length;i++) 
        {
            tourists[i]=new Tourist();
        }
        TourGuide guide = new TourGuide(0);
        guide.guide(tourists);
            Thread.sleep(500);
        guide.guide(tourists);

    }

}

The problem is I get this output: 问题是我得到以下输出:

Guide 0 is guiding 20 tourists
All tourists exited for guide 0. Going to shop
Guide 0 is free
Exception in thread "Thread-0" Guide 0 is guiding 20 tourists
java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
    at crossRoadConcurency.TourGide$1.run(TourGide.java:60)
    at java.lang.Thread.run(Unknown Source)
All tourists exited for guide 0. Going to shop
Guide 0 is free
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
    at crossRoadConcurency.TourGide$1.run(TourGide.java:60)
    at java.lang.Thread.run(Unknown Source)

First question : Why am I not seeing the "waiting output" 第一个问题 :为什么我看不到“等待输出”
Second question : Why am I getting an exception 第二个问题 :我为什么要例外
Third question : Is there a better way to do this, because I am fairly certain this concept is mixed up 第三个问题 :是否有更好的方法来执行此操作,因为我相当确定此概念会混淆

  1. You don't see "wait" because your guide is free by default. 您不会看到“等待”,因为您的指南默认情况下是免费的。 !isGuide && !isInShop returns true while you only print when !isFree() . !isGuide && !isInShop仅在!isFree()时打印时返回true。

  2. You should call lockObject.notifyAll() . 您应该调用lockObject.notifyAll() A direct call to notifyAll() by default invoke on this object and you certainly didn't hold the monitor of the anoymous object implementing Runnable interface because you never did by calling synchroized(this) . 默认情况下,直接调用notifyAll()对此对象进行调用,并且您肯定没有持有实现Runnable接口的异常对象的监视器,因为您从未通过调用synchroized(this) That's why you got the exception. 这就是为什么您遇到例外。

  3. Yes. 是。 You should use an Executor eg SingleThreadExecutor together with a concurrent queue. 您应该将Executor例如SingleThreadExecutor与并发队列一起使用。 That's the robust and easy way to implement concurrency unless you goes on high performance computing. 除非您进行高性能计算,否则这就是实现并发的强大而简单的方法。 That package also provide excellent functinoalities and supporting utilitiy classes. 该软件包还提供了出色的功能和支持的实用程序类。 Check out java.util.concurrent . 查看java.util.concurrent

BTW, your package name contains Upper letter which isn't recommended by java programming specification. 顺便说一句,您的程序包名称包含大写字母,Java编程规范不建议使用。

when we synchronize any block or method, we should synchronize on class lock or object lock. 当我们同步任何块或方法时,我们应该在类锁或对象锁上进行同步。

but here you have locked on some object which is no where related to caller of that method 但是在这里,您锁定了某个对象,该对象与该方法的调用者无关

so change this from synchronized (lockObject) to like below and run 因此,将其从synchronized (lockObject)更改为如下所示并运行

synchronized (this) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM