Java多线程,使一个线程等待另一个线程,或加入另一个线程 [英] Java Multi Threading, make a thread wait for another thread, or joining different thread

查看:185
本文介绍了Java多线程,使一个线程等待另一个线程,或加入另一个线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我第一次在这里问.在搜索之前,我曾获得过很多次帮助,并且始终能找到该网站.但是现在我找不到我的问题的答案.它有某种情况,还有许多其他问题,但我找不到我所需要的那个.

this is my first time asking here. I have many times helped before when searching and always found this site. But now I can't found the answer for my problem. It has some kind of situation with many other question, but I can't found the one that's in my need.

好的,所以我有一个叫玩家,农场和土地的班级.农场是一种控制者.农场有一个称为地图的对象数组,该对象与土地和玩家共享(建造时赋予),而地图内部是玩家和土地本身.

Okay, so I have class named player, farm, and land. Farm is the kind of controller. Farm have an array of object called map, which is shared with land and player (given when they are constructed), and inside the map is player and land itself.

我想做的是

我在农场上单击鼠标左键,然后根据单击的位置从地图上获取对象,然后将该对象保存为选定对象.然后,我右键单击其他对象并得到该对象,让其起作用.已执行操作的方法有一个getMenu(selected)方法,该方法基于selected返回一个JPopMenu.作为示例,如果选择了玩家,并且已执行着陆操作,则getMenu()将返回菜单犁",水"和移动".如果单击犁",则土地将发生变化,当然地图也将发生变化,与其他对象共享. 问题是,在犁的真正动作开始之前,我需要玩家首先走到土地附近的网格上.因此,在犁菜单中,我添加了一个这样的ActionListener:

I left-click on farm, and I got the object from map based on where I clicked, then I save that object as selected. Then I right click other object and got the object, lets call it actioned. Actioned have a method, getMenu(selected), which return a JPopMenu, based on selected. As an Example, if player is the selected, and land is actioned, the getMenu() will return menu "plow", "water" and "move". If I click at "plow", then the land will changed, and of course the map also changed, which shared with other object. The problem is, I need the player to walk to grid near the land first, before the real action of plow begin. So in the plow menu I add an ActionListener like this:

new ActionListener() {
        public void actionPerformed(ActionEvent e) {
                int gx = (int)Point2D.this.X();
                int gy = (int)Point2D.this.Y();
                Object lock = new Object();
                player.move(gx,gy,lock);
                try {
                    lock.wait();
                } catch (InterruptedException ex){}
                // do the real action of plow here
            }
        }
}

以及玩家的移动方法

public void move(int gx,int gy,Object lock){
    setDestination(gx, gy);
    this.lock = lock;
}

服务器场是一个Runnable对象,因此每次服务器场都会调用pl​​ayer.Update().

The farm is a Runnable object, so every time the farm will call player.Update().

public void update(){
    updatePosition();
    if (position==destination) {
        lock.notify();
    }
}

我想到了在那儿制作一个叫做锁的物体,然后把那个物体交给玩家.侦听器本身是一个正在运行的线程,单击菜单时启动,因此我根据锁定对象使侦听器的线程等待.通知是从服务器场线程给出的.

I thought of made an object called lock there, and that object given to player. the Listener is a running thread itself, and started when the menu is clicked, so I make the thread of Listener to wait, based on the lock object. The notify is given from the farm thread.

但是,当然,这不能很好地工作,并抛出java.lang.IllegalMonitorStateException.我真的没有从网络上得到什么同步解释. 问题1:我应如何在此处使用同步功能来使代码正常工作?或者,如果同步在这里永远无法工作,该怎么办?

But of course, that is not working well, and throw java.lang.IllegalMonitorStateException. I don't really get what the synchronization explanation from the web. Question 1: How should I use the synchronization here to make the code work? Or what should I do if the synchronization will never work here?

我还考虑过使用其他方法.

I have also thought of using other approach.

我使播放器成为可运行线程.现在我有3个线程,即场,侦听器(播放器)和播放器.

I make the player as a runnable thread to. Now I have 3 thread, the farm, listener(land), and player.

因此,我创建一个新的Thread(Player)而不是一个锁对象.播放器的运行方法:

So instead of make a lock object, I make a new Thread(Player). The run method of player:

while (position != destination) {
       try {
            Thread.sleep(100);
       } catch (InterruptedException e){}
   }

新的侦听器方法:

        Player player = (Player) selected;
        int gx = (int)Point2D.this.X();
        int gy = (int)Point2D.this.Y();

        player.move(gx,gy);
        Thread waitplayernotmoving = new Thread(player);
        waitplayernotmoving.start();
        try {
            waitplayernotmoving.join();
        } catch (InterruptedException e){}

它已经足够好了. 问题2:?等待玩家线程时,陆地线程是否停止工作?如果没有,如何在等待播放器线程死亡时停止登陆线程?

It is work well enough. Question 2: is the land thread stop working while waiting the player thread? if not, how to make the land thread to stop while waiting the player thread dead?

还有其他问题.如果我耕种土地1,然后在玩家移动时单击土地2并耕种土地2,则玩家将转向土地2!然后在不再移动之后,两地都被耕种了!表示land1的线程仍处于活动状态.

And I have other problem. If I plow land1, and then while the player moving, I click at land2 and plow land2, the player is turning to land2! And then after it is not moving again, both of the land is plowed! Meaning the thread of land1 is still active.

我有两个问题: 问题3:如果我为玩家设置了另一个动作(例如犁地2),是否有可能使land1线程死亡?

I have two question: Question 3: Is it possible to make the land1 thread die if I set another action to player, such as plow land2?

问题4:是否可以根据我的程序现在执行的操作,使land2线程在land1线程之后执行?所以动作就像一个队列.我先耕种土地1,然后耕种土地2,发生的动作将是玩家移至土地1,然后耕种土地1,然后移至土地2,再耕作土地2.

Question 4: Is it possible to make the land2 thread executed after land1 thread based on what my program doing now? So the action is like a queue. I plow land1, then plow land2, the action happen will be player move to land 1 and then plow land 1, then move to land2, and plow land 2.

问题5 还记得我的地图吗,共享给所有人的对象数组?如何确保安全?我的意思是,看起来会有很多线程在读写地图.我读过某个地方,如果它是不变的,那将不是问题.但是它经常被重写..会不会有问题?

Question 5 Remember my map, the array of object which is shared to all? How to ensure it is safe? I mean, looks like there will be many thread reading and writing the map. I read somewhere if it is immutable it won't be a problem. But it is re-written so often.. won't it be a problem?

非常感谢您阅读这份详尽的说明,希望您能给我答复. :(

Thank you very much for reading this long explanation, And I hope you can give me an answer. :(

推荐答案

我将回答以下问题5之一:

I'll just answer one of these Question 5:

您说如果它是不可变的,那不是问题",然后您说但它经常被重写"-我要说这意味着它不是不可变的.最简单的方法是在整个阵列上进行同步.

You say "if it's immutable it won't be a problem" then you say "but it's re-written so often" - which I am going to take means it's not immutable. The easiest way is to synchronize on the entire array.

synchronized (map) {
    // modify map
}

此操作的缺点是,您现在可以在任何想要修改数组的时间锁定所有其他线程(即使只有1个正在写入而10个正在读取).而且很可能多个并发线程实际上并不想修改同一元素,这应该没问题.您唯一需要担心的情​​况是,当多个线程想要更​​改相同的map元素时.第二种更精细的解决方案是读取/写入锁定.仅在我的线程想要更​​改整个地图时锁定整个地图,并且从不阻止读取. (请参见 ReentrantReadWriteLock )

The downfall of this is that you're now locking all your other threads anytime one wants to modify the array (even if only 1 is writing and 10 are reading). And there' a big possibility that multiple concurrent threads don't actually want to modify the same element which should be fine. The only case you need to worry about is when multiple threads want to change the same map element. A second, more granular solution would be a read/write lock. Only lock the entire map when I thread wants to change it, and never block on reads. (see ReentrantReadWriteLock )

readLock.lock();
try {
   // read from map
} finally {
   readLock.unlock();
}

writeLock.lock();
try {
   // modify map
} finally {
   writeLock.unlock();
}

现在有了更精细的粒度,您只锁定了地图中的单个元素-但这超出了我的范围. PLus让您自己思考.希望有帮助.

Now there is an even finer granularity where you only lock on individual elements in the map - but that's a little beyond the scope I think. PLus gives you something to think about on your own. Hope that helps.

这篇关于Java多线程,使一个线程等待另一个线程,或加入另一个线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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