2016-12-30 92 views
0

我有一个包含数据的对象,我正在用这个对象(动作将在其方法中使用对象的数据)排队一个Action(可以执行的方法的接口)和排队的Actions将从另一个线程执行。Java多线程问题

我想锁定对象后发送到行动队列(所以从我的主线程)。

因为我不希望对象的数据在其他线程通过动作队列处理之前被更改。

我想从另一个线程解锁对象,一旦行为队列被处理。

代码说明:

// THREAD 1 
final Object object = getObjectFromSomeWhere(); 

// lock the object here 

concurrentActionQueue.add(new Action() { 
     @Override 
     public void execute() { 
      // will be executed from THREAD 2 
      // do something with object 

      //unlock here once the data is processed 

     } 

你会说,我可以发送对象的副本的动作,但我的对象包含非常大的数据复制花费到太多的时间,所以我不能。

有没有办法做到这一点,没有硬编码lock()和unlock()方法到我的对象?

+0

消费者生产者也许格局?这里是一个非常简单的(不是最好的)[教程](https://www.tutorialspoint.com/javaexamples/thread_procon.htm)以 – AntJavaDev

回答

0

如果你想锁定所有主线程的执行,你可以使用CountDownLatch

// THREAD 1 
final Object object = getObjectFromSomeWhere(); 

final CountDownLatch latch = new CountDownLatch(1); 

concurrentActionQueue.add(new Action() { 
     @Override 
     public void execute() { 
      // will be executed from THREAD 2 
      // do something with object 

      latch.countDown(); 
     } 
} 

latch.await(); 

如果你想从其他线程被更改锁定对象数据,但可用线程的执行,你需要在你的Object课程中完成。我相信这不是一个对象。例如,您可以将对该对象的访问权的Thread引用传递给它,并在其中检查Thread.currentThread() == mAllowedThread;以了解此线程是否允许修改对象。

另外,你可以使用一些OO方式来处理这个问题,例如让你的对象拥有包本地设置器并传递一个包含setter的包装器给这个动作。很难说什么是解决方案,因为我没有看到你的实际问题。希望我的一些建议可以帮助你。

+0

开头我的问题是,当我发送我的数据(对象)到行动队列,这是一个很好的格式。但是数据会持久地改变,并且当数据不再是一个很好的格式(同时从线程1被修改)时这个动作可能被执行,这是危险的。我的线程2是一个渲染器,它需要网格的有序数据。 – aqww

+0

你是什么意思下的“锁定/解锁”对象?其他线程在尝试更改对象时应如何处理? –

+0

那么有多种可能性,其中一个是其他线程可能必须等到解锁之后才对数据进行任何修改。或者我可以硬编码一些可以在队列锁定时对数据进行每次修改的队列,并在不再锁定时执行。 – aqww

0

线程之间只有通用的引用是你的对象,因此实现锁定你必须修改你的对象。如果你不想修改你的对象,你可以写一个助手类,它将使用倒计时闩锁来执行任务。并在你的所有线程中传递这个辅助类的引用。 看看这是你在找什么 -

final YourObject object = getObjectFromSomeWhere(); 

class HelperObject { 
YourObject object; 
public HelperObject(YourObject object){ 
this.object = object; 
} 
final CountDownLatch latch = new CountDownLatch(1); 
    public void countDown(){ 
    latch.countDown(); 
    } 

    public void await(){ 
    latch.await(); 
    } 
} 

concurrentActionQueue.add(new Action() { 
    @Override 
    public void execute() { 
     // will be executed from THREAD 2 
     HelperObject helperObj;// do something with object 

     helperObj.countDown(); 
    } 
}