顺序和并行处理
2022-09-02 23:44:35
						我有一个生产者和许多消费者。
- 生产者速度快,产生很多结果
- 具有相同值的令牌需要按顺序处理
- 必须并行处理具有不同值的令牌
- 创建新的Runnables将非常昂贵,并且生产代码也可以使用100k的Token(为了创建Runnable,我必须传递给构造函数一些复杂的来构建对象)
我可以使用更简单的算法获得相同的结果吗?使用重入锁定嵌套同步块似乎有点不自然。您是否注意到任何争用条件?
更新:我发现的第二个解决方案是使用3个集合。一个用于缓存生产者结果,第二个是阻塞队列,第三个使用列表来跟踪正在进行的任务。再次有点复杂。
我的代码版本
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantLock;
public class Main1 {
    static class Token {
        private int order;
        private String value;
        Token() {
        }
        Token(int o, String v) {
            order = o;
            value = v;
        }
        int getOrder() {
            return order;
        }
        String getValue() {
            return value;
        }
    }
    private final static BlockingQueue<Token> queue = new ArrayBlockingQueue<Token>(10);
    private final static ConcurrentMap<String, Object> locks = new ConcurrentHashMap<String, Object>();
    private final static ReentrantLock reentrantLock = new ReentrantLock();
    private final static Token STOP_TOKEN = new Token();
    private final static List<String> lockList = Collections.synchronizedList(new ArrayList<String>());
    public static void main(String[] args) {
        ExecutorService producerExecutor = Executors.newSingleThreadExecutor();
        producerExecutor.submit(new Runnable() {
            public void run() {
                Random random = new Random();
                    try {
                        for (int i = 1; i <= 100; i++) {
                            Token token = new Token(i, String.valueOf(random.nextInt(1)));
                            queue.put(token);
                        }
                        queue.put(STOP_TOKEN);
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
        });
        ExecutorService consumerExecutor = Executors.newFixedThreadPool(10);
        for(int i=1; i<=10;i++) {
            // creating to many runnable would be inefficient because of this complex not thread safe object
            final Object dependecy = new Object(); //new ComplexDependecy()
            consumerExecutor.submit(new Runnable() {
                public void run() {
                    while(true) {
                        try {
                            //not in order
                            Token token = queue.take();
                            if (token == STOP_TOKEN) {
                                queue.add(STOP_TOKEN);
                                return;
                            }
                            System.out.println("Task start" + Thread.currentThread().getId() + " order "  + token.getOrder());
                            Random random = new Random();
                            Thread.sleep(random.nextInt(200)); //doLongRunningTask(dependecy)
                            lockList.remove(token.getValue());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
            }});
    }
}}
 
					 
				 
				    		 
				    		 
				    		