使用while循环强制代码等待条件需要thread.sleep()

问题描述 投票:0回答:1

我创建了一个程序,将线性搜索(搜索-1)划分为4个单独的线程。

public class main {

    static boolean found = false;

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        int threadCount = 4; //amount of threads to use
        Random rand = new Random();
        Searcher[] s_arr = new Searcher[threadCount]; //array of threads


        int[] arr = new int[10000]; //array to search through
        for (int i = 0; i < arr.length; i++) //randomizing #'s in array
            arr[i] = (int) (rand.nextFloat() * 1000);

        int randIndex = rand.nextInt(arr.length); //choose random index

        arr[randIndex] = -1; //set random index to = -1

        for (int i = 0; i < threadCount; i++) { //
            s_arr[i] = new Searcher(Arrays.copyOfRange(arr, i * (arr.length/threadCount), (i+1) * (arr.length/threadCount)), 
                    (int) (i), i); //assign subarray for this thread to search through
            System.out.println(s_arr[i].wait);
            s_arr[i].start(); 
        }


        //CODE IN QUESTION HERE ----------------------------
        //while (!found) ;

        while (!found) //wait until value is found
        {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
//-----------------------------------------------------------





        System.out.println("found!");

        for (int i = 0; i < threadCount; i++) {
            try {
                s_arr[i].join(); //wait for the threads in order before continuing
                System.out.println("Thread ["+i+"] completed");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("All threads stopped, program complete.");
    }

}

public class Searcher extends Thread {

    int[] arr;
    int wait;
    int index;

    public Searcher(int[] arr, int wait, int i) {
        this.arr = arr;
        this.wait = wait;
        this.index = i;
    }

    @Override
    public void run() {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == -1) {
                System.out.println("["+index+"] -1 Found at index: "+i);
                main.found = true;
                break;
            }
            if (main.found) break;
            //purposely slow down this thread
            try {
                Thread.sleep(wait);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("["+index+"] has stopped");

    }

}

我已经标记了有问题的代码,在使用第一个(注释掉)的while循环时,程序不会超出该点,但是如果我切换并在其下面使用另一个while循环(强制每个迭代器等待1毫秒),程序运行正常。

为什么这样做,有没有更有效/实用的方法来完成此任务?

java multithreading
1个回答
2
投票

[在空循环语句的情况下反复读取非易失性字段可能会导致无限循环,因为编译器优化可能会将对该字段的访问移出了循环。

来源:help.semmle.com

如果将static boolean found = false;替换为volatile static boolean found = false;,则第一个循环将起作用,但我不建议这样做,因为这会浪费您的CPU时间。您应该考虑使用waitnotify

static boolean found下方,添加static final Object lock = new Object();并用]替换两个while循环>

try {
    synchronized (lock) {
        // we will wait here until we get notified
        lock.wait();
    }
} catch (InterruptedException e) {
    e.printStackTrace();
}

也在main.found = true添加之后

synchronized (main.lock) {
    main.lock.notify();
}

最后,您的代码应该看起来像这样

public class main {

    static boolean found;
    static final Object lock = new Object();

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        int threadCount = 4; //amount of threads to use
        Random rand = new Random();
        Searcher[] s_arr = new Searcher[threadCount]; //array of threads


        int[] arr = new int[10000]; //array to search through
        for (int i = 0; i < arr.length; i++) //randomizing #'s in array
            arr[i] = (int) (rand.nextFloat() * 1000);

        int randIndex = rand.nextInt(arr.length); //choose random index

        arr[randIndex] = -1; //set random index to = -1

        for (int i = 0; i < threadCount; i++) { //
            s_arr[i] = new Searcher(Arrays.copyOfRange(arr, i * (arr.length/threadCount), (i+1) * (arr.length/threadCount)),
                    (int) (i), i); //assign subarray for this thread to search through
            System.out.println(s_arr[i].wait);
            s_arr[i].start();
        }

        try {
            synchronized (lock) {
                lock.wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("found!");

        for (int i = 0; i < threadCount; i++) {
            try {
                s_arr[i].join(); //wait for the threads in order before continuing
                System.out.println("Thread ["+i+"] completed");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("All threads stopped, program complete.");
    }

}

class Searcher extends Thread {

    int[] arr;
    int wait;
    int index;

    public Searcher(int[] arr, int wait, int i) {
        this.arr = arr;
        this.wait = wait;
        this.index = i;
    }

    @Override
    public void run() {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == -1) {
                System.out.println("["+index+"] -1 Found at index: "+i);
                main.found = true;
                synchronized (main.lock) {
                    main.lock.notify();
                }
                break;
            }
            if (main.found) break;
            //purposely slow down this thread
            try {
                Thread.sleep(wait);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println("["+index+"] has stopped");

    }

}
© www.soinside.com 2019 - 2024. All rights reserved.