消费者和工人模式

时间:2012-04-24 13:19:33

标签: java multithreading arraylist deque

我有10名工人名单的代码和以下两种方法:

public void demoDeques() {
        int maxSizeOfJobDeque = 3;
        Producer producer = new ProducerImpl( maxSizeOfJobDeque );

        Logger.debug( "WorkFlowEngineImpl : " +
                "Creating Workers and adding them to allocator" );
        List<Worker> workerList = buildWorkerList( producer );
        Logger.debug( "WorkFlowEngineImpl : " +
                "Assigning some jobs to the workers. " +
                    "The workers have not been started yet");

        for ( int i=1; i<4; i++ ) {
            producer.assign( new JobImpl( "job " + i, i ) );
            try {
                Thread.sleep( 4000 );
            } catch( InterruptedException e ) {
                e.printStackTrace();
            }
        }

        Logger.debug( "WorkFlowEngineImpl : " + "Starting the workers" );
        startWorkersAndWait5Seconds( workerList );
        Logger.debug( "WorkFlowEngineImpl : " +
                "Assigning some more jobs to the " +
                    "started workers" );

        for ( int i=4; i<7; i++ ) {
            producer.assign( new JobImpl( "Job " + i, i ) );
            try {
                Thread.sleep( 4000 );
            } catch( InterruptedException e ) {
                e.printStackTrace();
            }
        }

        Logger.debug( "WorkFlowEngineImpl : " + "Assigning More Jobs" );
        for ( int i=7; i<11; i++ ) {
            producer.assign( new JobImpl( "job" + i, i ) );
            try {
                Thread.sleep( 4000 );
            } catch( InterruptedException e ) {
                e.printStackTrace();
            }
        }
    }

生产者:

public synchronized void assign( Job job ) {
    Set<Worker> workerSet = jobMap.keySet();
    LinkedBlockingDeque<Job> jobQueue;
    StringBuffer sb;

    for ( Worker worker : workerSet ) {
        jobQueue = jobMap.get( worker );

        sb = new StringBuffer();
        sb.append( "Assigning job " );
        sb.append( job.getJobNumber() );
        sb.append( " to " );
        sb.append( worker );
        sb.append( "'s jobs Deque" );

        Logger.debug( "Producer : " + sb.toString() );

        if ( ! jobQueue.offerFirst( job ) ) { 
            jobQueue.pollLast();
            jobQueue.offerFirst( job );
        }
    }
}

我正在尝试更改这两种方法,以便我让分配器具有100个作业的列表,然后以这样的方式分配:十个工作程序中的每一个在时间上最多给予三个作业,直到达到100为止,即工人1需要工作1,2,3工人2需要4,5,6这样当工人10到达时,它会返回工作人员,分配三个工作直到达到第100个工作,然后它停止并警告所有工作已分配。请帮助我被困......

2 个答案:

答案 0 :(得分:2)

虽然您的问题提到了具体的执行顺序,但您的意见似乎表明这不是真正的要求。我建议您使用Java 1.5中提供的Executors,而不是实现自己的线程池。例如:

ExecutorService threadPool =
    Executors.newFixedThreadPool(NUMBER_THREADS_TO_RUN_JOBS);
// your producers then just have to submit jobs to the pool
for ( int i=1; i<4; i++ ) {
    threadPool.submit(new JobImpl("Job " + i, i));
}

我无法从您的示例中确切地看到每个“作业”需要进行哪些处理,但如果JobImpl需要实现Runnable以使上述代码生效。如果您需要从工作中返回一些值,则可以将JobImpl更改为Callable并使用Future方法返回的submit(Callable)来获取{返回的结果} {1}}。

答案 1 :(得分:1)

我不同意您的工作分配方法,我认为这就是挂断您的代码。

通常,生产者应该创建工作并将其分配给队列。担心生产工作不是生产者的责任。当工人可以使用时,他们会从队列中取出工作。无论是拉1个工作还是3个工作,都只是工作线程中的逻辑问题。

您可能希望为队列创建单例类。它应该处理接收和请求工作。

通过这种方式接近它可以让工人与生产者分离。您可以根据工作负载/瓶颈要求添加更多生产者或工作者。它还可以防止您生成某种信号机制,工作人员向生产者表明他们已准备好开展更多工作。最后,这使您不必担心各种竞争条件,其中只有一个作业可用,或者作业编号与您在demoDequeue中的幻数不一致。

HTH,对不起,这不是一个直接的答案,但应该让你找到解决问题的更好途径。