有没有办法让多个线程顺序访问共享资源列表?

Posted

技术标签:

【中文标题】有没有办法让多个线程顺序访问共享资源列表?【英文标题】:Is there a way for multiple threads to sequentially access a list of shared resources? 【发布时间】:2019-08-21 02:51:12 【问题描述】:

有没有办法让多个线程顺序访问共享资源列表,我有两个线程 t1 和 t2,我想根据条件访问对象列表,我希望每个线程之前只处理一次允许其他线程。

class items(int itemid, String itemname, int priority)

示例输入:

[ 123,"item1", 8 ], [124, "item2", 2], [125, "item3", 5 ], [126,"item4", 3]

预期输出:

Thread1: Processing Item - 123, priority - 8,
Thread2: Processing Item - 125, priority - 5,
Thread1: Processing Item - 126, priority - 3,
Thread2: Processing Item - 124, priority - 2,

尝试使用具有同步的优先级队列,但无法按顺序访问对象列表。

public class Items implements Comparable<Items>
private int itemID;
private String itemname;
private int priority;

public Items(int itemID, String itemname, int priority)

    this.itemID = itemID;
    this.itemname = itemname;
    this.priority = priority;

public int getItemID() 
    return itemID;



public void setItemID(int itemID) 
    this.itemID = itemID;



public String getItemname() 
    return itemname;



public void setItemname(String itemname) 
    this.itemname = itemname;



public int getPriority() 
    return priority;



public void setPriority(int priority) 
    this.priority = priority;



@Override
public int compareTo(Items item) 

    return item.priority > this.priority ? 1 : item.priority < this.priority ? -1 :0;



package multithreading;

import java.util.concurrent.PriorityBlockingQueue;

public class itemsImpl 

    private static PriorityBlockingQueue<Items> priorityQueue;

    public static void main(String[] args)
    
        priorityQueue = new PriorityBlockingQueue<Items>();

        priorityQueue.add(new Items( 123,"item1", 8));
        priorityQueue.add(new Items( 124, "item2", 2));
        priorityQueue.add(new Items( 125, "item3", 5));
        priorityQueue.add(new Items( 126,"item4", 3));

        itemsImpl impl = new itemsImpl();

        Thread t1 = new Thread( new Runnable()
        public void run()
        
            try 
                impl.pollQueue(Thread.currentThread().getName());
             catch (InterruptedException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            
        );

        Thread t2 = new Thread( () -> 
            try 
                impl.pollQueue(Thread.currentThread().getName());
             catch (InterruptedException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            
         );
        t1.start();
        t2.start();
        


    private void pollQueue(String name) throws InterruptedException
       
        while(priorityQueue.size()>0)
        
            synchronized(this)
               
                    Items i = priorityQueue.poll();
                    System.out.println(name +": Items Processsing - " + i.getItemID() + ", priority - " + i.getPriority());
                    Thread.sleep(100);
            

        


    


【问题讨论】:

能否请您也添加实际输出? 参考预期输出 线程 1:处理项目 - 123,优先级 - 8,线程2:处理项目 - 125,优先级 - 5,线程1:处理项目 - 126,优先级 - 3,线程 2:处理项目 - 124,优先级 - 2、 【参考方案1】:

你需要添加一个标志来定义哪个线程应该处理下一个项目。

public class itemsImpl 

    private static PriorityBlockingQueue<Items> priorityQueue;
    private volatile boolean flag = false; //flag to define which thread should proceed

    public static void main(String[] args) 
        priorityQueue = new PriorityBlockingQueue<Items>();

        priorityQueue.add(new Items( 123,"item1", 8));
        priorityQueue.add(new Items( 124, "item2", 2));
        priorityQueue.add(new Items( 125, "item3", 5));
        priorityQueue.add(new Items( 126,"item4", 3));

        itemsImpl impl = new itemsImpl();

        Thread t1 = new Thread( new Runnable()
            public void run() 
                try 
                    impl.pollQueue(Thread.currentThread().getName(), false);
                 catch (InterruptedException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
        );

        Thread t2 = new Thread( () -> 
            try 
                impl.pollQueue(Thread.currentThread().getName(), true);
             catch (InterruptedException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            
         );
        t1.start();
        t2.start();
    


    private void pollQueue(String name, boolean expected) throws InterruptedException 
        while(priorityQueue.size()>0) 
            synchronized(this) 
                while (flag != expected)  // thread is waiting for its turn
                    this.wait();
                
                Items i = priorityQueue.take(); //You need to either use blocking take() or check that item is not null
                System.out.println(name +": Items Processsing - " + i.getItemID() + ", priority - " + i.getPriority());
                flag = !expected;
                this.notifyAll();
            
        
    

【讨论】:

以上是关于有没有办法让多个线程顺序访问共享资源列表?的主要内容,如果未能解决你的问题,请参考以下文章

iOS线程同步(各种锁)

多线程线程同步

对象的共享

java中的同步与异步

资源竞争

线程顺序同步