【问题标题】:Java multi-threading issueJava多线程问题
【发布时间】:2016-12-30 21:09:55
【问题描述】:

我有一个包含数据的对象,我正在使用该对象排队一个动作(与可以执行的方法的接口)(该动作将在其方法中使用对象的数据),并且排队的动作将被执行来自另一个线程。

我想在将对象发送到操作队列后锁定它(所以从我的主线程)。

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

我希望在处理动作队列后从另一个线程解锁对象。

代码说明:

// 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

        }

您会说我可以将对象的副本发送到 Action,但我的对象包含非常大的数据并且复制需要很长时间,所以我不能。

有没有办法在我的对象不硬编码 lock() 和 unlock() 方法的情况下做到这一点?

【问题讨论】:

  • 消费者生产者模式可能吗?这是一个非常简单(不是最好的)tutorial 开始

标签: java multithreading


【解决方案1】:

如果要锁定所有主线程的执行,可以使用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; 以了解该线程是否允许修改对象。

此外,您可以使用一些面向对象的方式来处理它,例如让您的对象具有包本地设置器并传递一个可以访问设置器的包装器到操作。很难说什么是解决方案,因为我没有看到你的实际问题。希望我的一些建议也能对你有所帮助。

【讨论】:

  • 我的问题是当我将数据(对象)发送到动作队列的那一刻,它的格式很好。但是数据会持续更改,并且可以在数据不再处于良好格式(从线程 1 修改时)的时刻执行操作,这很危险。我的线程 2 是一个渲染器,它的网格需要有序的数据。
  • 你在“锁定/解锁”对象下是什么意思?其他线程在尝试更改对象时应该如何表现?
  • 好吧,可能性不止一种,一种是其他线程可能必须等到解锁才能对数据进行任何修改。或者我可以硬编码一些东西,在数据锁定时对数据进行的每次修改都会放入队列,并在不再锁定时执行。
【解决方案2】:

只有线程之间的共同引用是您的对象,因此要实现锁定,您必须修改您的对象。如果您不想修改您的对象,您可以编写一个辅助类,该类将使用倒计时锁存器来执行任务。并在所有线程之间传递这个帮助类引用。 看看这是不是你要找的 -

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();   
    }
}

【讨论】:

    猜你喜欢
    • 2016-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 2016-12-12
    • 2011-09-11
    • 1970-01-01
    • 2023-03-26
    相关资源
    最近更新 更多