1

首先,这是一个鼓舞人心的例子:

public class Algorithm
{
    public static void compute(Data data)
    {
        List<Task> tasks = new LinkedList<Task>();
        Client client = new Client();
        int totalTasks = 10;

        for(int i = 0; i < totalTasks; i++)
            tasks.add(new Task(data));

         client.submit(tasks);
    }
}

// AbstractTask implements Serializable
public class Task extends AbstractTask
{
    private final Data data;

    public Task(Data data)
    {
        this.data = data;
    }

    public void run()
    {
        // Do some stuff with the data.
    }
}

所以,我正在做一些并行编程,并且有一种方法可以创建大量任务。这些任务共享他们将要操作的数据,但是我在为每个任务提供对数据的引用时遇到了问题。问题是,当任务被序列化时,会为每个任务制作一份数据副本。现在,在这个任务类中,我可以对数据进行静态引用,以便它只存储一次,但是在任务类的上下文中这样做并没有多大意义。我的想法是将对象作为静态存储在另一个外部类中,并让任务从类中请求对象。这可以在发送任务之前完成,很可能在上面发布的示例中的计算方法中完成。你觉得这样合适吗?任何人都可以就建议的想法提供任何替代解决方案或提示吗?谢谢!

4

5 回答 5

1

Can you explain more about this serialization situation you're in? How do the Tasks report a result, and where does it go -- do they modify the Data? Do they produce some output? Do all tasks need access to all the Data? Are any of the Tasks written to the same ObjectOutputStream?

Abstractly, I guess I can see two classes of solutions.

  1. If the Tasks don't all need access to all the Data, I would try to give each Task only the data that it needs.
  2. If they do all need all of it, then instead of having the Task contain the Data itself, I would have it contain an ID of some kind that it can use to get the data. How to get just one copy of the Data transferred to each place a Task could run, and give the Task access to it, I'm not sure, without better understanding the overall situation. But I would suggest trying to manage the Data separately.
于 2009-07-03T09:29:08.557 回答
0

我的想法是将对象作为静态存储在另一个外部类中,并让任务从类中请求对象。

忘记这个想法。当任务被序列化并通过网络发送时,该对象将不会被发送;静态数据不会(也不能)在 JVM 之间以任何方式共享。

基本上,如果您的任务是单独序列化的,那么共享数据的唯一方法是单独发送它,或者只在一个任务中发送它,然后让其他任务在接收机器上获取它。这可能通过具有数据集的一个任务和其他任务查询的静态字段发生,但当然这需要首先运行一个任务。它可能导致同步问题。

但实际上,听起来您正在使用某种假定任务是自包含的处理队列。通过试图让他们共享数据,你违背了这个概念。无论如何,您的数据有多大?共享数据真的绝对必要吗?

于 2009-07-03T09:43:50.220 回答
0

编辑:由于对所问内容的误解,以下答案实际上并不相关。将其留在这里等待问题作者的更多细节。


这正是transient发明关键字的原因。

声明实例字段不是对象的默认序列化形式的一部分。当一个对象被序列化时,只有它的非瞬态实例字段的值被包含在默认的序列表示中。反序列化对象时,瞬态字段仅初始化为其默认值。

public class Task extends AbstractTask {
    private final transient Data data;

    public Task(Data data) {
        this.data = data;
    }

    public void run() {
        // Do some stuff with the data.
    }
}
于 2009-06-30T15:19:43.183 回答
0

我不确定我是否完全理解这个问题,但在我看来,任务实际上是序列化以供以后执行的。

如果是这种情况,一个重要的问题是是否所有Task对象都写入同一个ObjectOutputStream. 如果是这样,Data则只会在第一次遇到时对其进行序列化。稍后的“副本”将仅从流中引用相同的对象句柄。

也许可以利用这一点来避免对数据的静态引用(这可能会导致 OO 设计中的许多问题)。

于 2009-06-30T15:21:24.243 回答
0

您是否考虑过制作单例而不是使其成为静态?

于 2009-06-30T15:42:29.503 回答