如何在 Java 中实现多线程广度优先搜索?

我已经用常规方式完成了广度优先搜索。现在我正尝试用多线程的方式来实现它。我有一个队列,它在线程之间共享。当从队列中移除一个节点(FIFO队列)时,我使用了 synchronize(LockObject)。我想要做的是,当一个线程找到解决方案时,所有其他线程会立即停止。


回答:

我已经成功地实现了它。我所做的是,我获取了第一层的所有节点,假设有4个节点。然后我有2个线程。每个线程获取2个节点并生成它们的子节点。每当一个节点找到解决方案时,它必须报告找到解决方案的层级,并限制搜索层级,以便其他线程不会超过该层级。

只有报告方法应该被同步。

我完成了硬币找零问题的代码。这是我的代码,供其他人使用

主类 (CoinsProblemBFS.java)

package coinsproblembfs;import java.util.ArrayList;import java.util.LinkedList;import java.util.List;import java.util.Queue;import java.util.Scanner;/** * * @author Kassem M. Bagher */public class CoinsProblemBFS{    private static List<Item> MoneyList = new ArrayList<Item>();    private static Queue<Item> q = new LinkedList<Item>();    private static LinkedList<Item> tmpQ;    public static Object lockLevelLimitation = new Object();    public static int searchLevelLimit = 1000;    public static Item lastFoundNode = null;    private static int numberOfThreads = 2;    private static void InitializeQueu(Item Root)    {        for (int x = 0; x < MoneyList.size(); x++)        {            Item t = new Item();            t.value = MoneyList.get(x).value;            t.Totalvalue = MoneyList.get(x).Totalvalue;            t.Title = MoneyList.get(x).Title;            t.parent = Root;            t.level = 1;            q.add(t);        }    }    private static int[] calculateQueueLimit(int numberOfItems, int numberOfThreads)    {        int total = 0;        int[] queueLimit = new int[numberOfThreads];        for (int x = 0; x < numberOfItems; x++)        {            if (total < numberOfItems)            {                queueLimit[x % numberOfThreads] += 1;                total++;            }            else            {                break;            }        }        return queueLimit;    }    private static void initializeMoneyList(int numberOfItems, Item Root)    {        for (int x = 0; x < numberOfItems; x++)        {            Scanner input = new Scanner(System.in);            Item t = new Item();            System.out.print("Enter the Title and Value for item " + (x + 1) + ": ");            String tmp = input.nextLine();            t.Title = tmp.split(" ")[0];            t.value = Double.parseDouble(tmp.split(" ")[1]);            t.Totalvalue = t.value;            t.parent = Root;            MoneyList.add(t);        }    }    private static void printPath(Item item)    {        System.out.println("\nSolution Found in Thread:" + item.winnerThreadName + "\nExecution Time: " + item.searchTime + " ms, " + (item.searchTime / 1000) + " s");        while (item != null)        {            for (Item listItem : MoneyList)            {                if (listItem.Title.equals(item.Title))                {                    listItem.counter++;                }            }            item = item.parent;        }        for (Item listItem : MoneyList)        {            System.out.println(listItem.Title + " x " + listItem.counter);        }    }    public static void main(String[] args) throws InterruptedException    {        Item Root = new Item();        Root.Title = "Root Node";        Scanner input = new Scanner(System.in);        System.out.print("Number of Items: ");        int numberOfItems = input.nextInt();        input.nextLine();        initializeMoneyList(numberOfItems, Root);                System.out.print("Enter the Amount of Money: ");        double searchValue = input.nextDouble();        int searchLimit = (int) Math.ceil((searchValue / MoneyList.get(MoneyList.size() - 1).value));        System.out.print("Number of Threads (Muste be less than the number of items): ");        numberOfThreads = input.nextInt();        if (numberOfThreads > numberOfItems)        {            System.exit(1);        }        InitializeQueu(Root);        int[] queueLimit = calculateQueueLimit(numberOfItems, numberOfThreads);        List<Thread> threadList = new ArrayList<Thread>();        for (int x = 0; x < numberOfThreads; x++)        {            tmpQ = new LinkedList<Item>();            for (int y = 0; y < queueLimit[x]; y++)            {                tmpQ.add(q.remove());            }            BFS tmpThreadObject = new BFS(MoneyList, searchValue, tmpQ);            Thread t = new Thread(tmpThreadObject);            t.setName((x + 1) + "");            threadList.add(t);        }        for (Thread t : threadList)        {            t.start();        }        boolean finish = false;        while (!finish)        {            Thread.sleep(250);            for (Thread t : threadList)            {                if (t.isAlive())                {                    finish = false;                    break;                }                else                {                    finish = true;                }            }        }        printPath(lastFoundNode);    }}

Item 类 (Item.java)

package coinsproblembfs;/** * * @author Kassem */public class Item{    String Title = "";    double value = 0;    int level = 0;    double Totalvalue = 0;    int counter = 0;    Item parent = null;    long searchTime = 0;    String winnerThreadName="";}

Threads 类 (BFS.java)

package coinsproblembfs;import java.util.ArrayList;import java.util.LinkedList;import java.util.List;/** * * @author Kassem M. Bagher */public class BFS implements Runnable{    private LinkedList<Item> q;    private List<Item> MoneyList;    private double searchValue = 0;    private long start = 0, end = 0;    public BFS(List<Item> monyList, double searchValue, LinkedList<Item> queue)    {        q = new LinkedList<Item>();        MoneyList = new ArrayList<Item>();        this.searchValue = searchValue;        for (int x = 0; x < queue.size(); x++)        {            q.addLast(queue.get(x));        }        for (int x = 0; x < monyList.size(); x++)        {            MoneyList.add(monyList.get(x));        }    }    private synchronized void printPath(Item item)    {        while (item != null)        {            for (Item listItem : MoneyList)            {                if (listItem.Title.equals(item.Title))                {                    listItem.counter++;                }            }            item = item.parent;        }        for (Item listItem : MoneyList)        {            System.out.println(listItem.Title + " x " + listItem.counter);        }    }    private void addChildren(Item node, LinkedList<Item> q, boolean initialized)    {        for (int x = 0; x < MoneyList.size(); x++)        {            Item t = new Item();            t.value = MoneyList.get(x).value;            if (initialized)            {                t.Totalvalue = 0;                t.level = 0;            }            else            {                t.parent = node;                t.Totalvalue = MoneyList.get(x).Totalvalue;                if (t.parent == null)                {                    t.level = 0;                }                else                {                    t.level = t.parent.level + 1;                }            }            t.Title = MoneyList.get(x).Title;            q.addLast(t);        }    }    @Override    public void run()    {        start = System.currentTimeMillis();        try        {            while (!q.isEmpty())            {                Item node = null;                node = (Item) q.removeFirst();                node.Totalvalue = node.value + node.parent.Totalvalue;                if (node.level < CoinsProblemBFS.searchLevelLimit)                {                    if (node.Totalvalue == searchValue)                    {                        synchronized (CoinsProblemBFS.lockLevelLimitation)                        {                            CoinsProblemBFS.searchLevelLimit = node.level;                            CoinsProblemBFS.lastFoundNode = node;                            end = System.currentTimeMillis();                            CoinsProblemBFS.lastFoundNode.searchTime = (end - start);                            CoinsProblemBFS.lastFoundNode.winnerThreadName=Thread.currentThread().getName();                        }                    }                    else                    {                        if (node.level + 1 < CoinsProblemBFS.searchLevelLimit)                        {                            addChildren(node, q, false);                        }                    }                }            }        } catch (Exception e)        {            e.printStackTrace();        }    }}

样例输入:

Number of Items: 4Enter the Title and Value for item 1: one 1Enter the Title and Value for item 2: five 5Enter the Title and Value for item 3: ten 10Enter the Title and Value for item 4: twenty 20Enter the Amount of Money: 150Number of Threads (Muste be less than the number of items): 2

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注