Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用多线程的数独解算器_Java_Multithreading_Performance - Fatal编程技术网

Java 使用多线程的数独解算器

Java 使用多线程的数独解算器,java,multithreading,performance,Java,Multithreading,Performance,我已经使用回溯实现了一个数独解算器,但是我有性能问题,主要问题是isAvailable()函数检查数字是否对当前位置有效。不使用线程的执行时间为61ms: protected boolean flag; public boolean isAvailable(int sudoku[][], int row, int col, int num){ flag = true; int rowStart = (row / 3) * 3; int colStart = (col

我已经使用回溯实现了一个数独解算器,但是我有性能问题,主要问题是
isAvailable()
函数检查数字是否对当前位置有效。不使用线程的执行时间为
61ms

protected boolean flag;

public boolean isAvailable(int sudoku[][], int row, int col, int num){
    flag = true;

    int rowStart = (row / 3) * 3;
    int colStart = (col / 3) * 3;

    for (int i = 0; i < 9; ++i) {
        if (sudoku[row][i] == num) {
            flag = false;
        }
    }

    for (int i = 0; i < 9; ++i) {
        if (sudoku[i][col] == num) {
            flag = false;
        }
    }

    for (int i = rowStart; i < (rowStart + 3); ++i) {
        for (int j = colStart; j < (colStart + 3); ++j) {
            if (sudoku[i][j] == num)
                flag = false;
        }
    }

    return flag;
}
但是,如果我使用不同的线程,一个用于检查行,另一个用于检查列,另一个用于检查框,我希望执行时间更短,但大约需要312s时间

protected boolean flag;

public boolean isAvailable(int sudoku[][], int row, int col, int num) throws InterruptedException {
    flag = true;

    int rowStart = (row / 3) * 3;
    int colStart = (col / 3) * 3;

    Thread t1 = new Thread(new Runnable() {
        public void run() {
            for (int i = 0; i < 9; ++i) {
                if (sudoku[row][i] == num) {
                    flag = false;
                }
            }
        }

    });
    t1.start();

    Thread t2 = new Thread(new Runnable() {
        public void run() {
            for (int i = 0; i < 9; ++i) {
                if (sudoku[i][col] == num) {
                    flag = false;
                }
            }
        }

    });
    t2.start();


    Thread t3 = new Thread(new Runnable() {
        public void run() {
            for (int i = rowStart; i < (rowStart + 3); ++i) {
                for (int j = colStart; j < (colStart + 3); ++j) {
                    if (sudoku[i][j] == num)
                        flag = false;
                }
            }
        }
    });
    t3.start();

    t1.join();
    t2.join();
    t3.join();

    return flag;
}
如果您需要我的完整代码:

import java.text.DecimalFormat;

public class Main {

    public static void main(String[] args){

          int sudoku[][] = {{8, 0, 0, 0, 0, 0, 0, 0, 0},
                            {0, 0, 3, 6, 0, 0, 0, 0, 0},
                            {0, 7, 0, 0, 9, 0, 2, 0, 0},
                            {0, 5, 0, 0, 0, 7, 0, 0, 0},
                            {0, 0, 0, 0, 4, 5, 7, 0, 0},
                            {0, 0, 0, 1, 0, 0, 0, 3, 0},
                            {0, 0, 1, 0, 0, 0, 0, 6, 8},
                            {0, 0, 8, 5, 0, 0, 0, 1, 0},
                            {0, 9, 0, 0, 0, 0, 4, 0, 0}};

        Main m = new Main();
        long starttime = System.nanoTime();
        boolean k = m.fillsudoku(sudoku, 0, 0);
        long endtime = System.nanoTime();

        DecimalFormat df = new DecimalFormat("#.##");

        if (k) {
            System.out.println("Answer found");
            System.out.println("Time elapsed = " + df.format((double) (endtime - starttime) / 1000000) + "ms");
            for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    System.out.print(sudoku[i][j] + " ");
                }
                System.out.println();
            }
        } else {
            System.out.println("Not found");
        }
    }

    public boolean fillsudoku(int sudoku[][], int row, int col){
        if(row < 9){
            if(sudoku[row][col] != 0){
                if(col < 8){
                    return fillsudoku(sudoku, row, col+1);
                }
                else if(row < 8){
                    return fillsudoku(sudoku, row+1, 0);
                }
                return true;
            }
            else{
                for(int i=1;i<=9;i++){
                    if(isAvailable(sudoku, row, col, i)){        // <- checking function
                        sudoku[row][col] = i;
                        if(col == 8){
                            if(fillsudoku(sudoku, row+1, 0)){
                                return true;
                            }
                        }
                        else{
                            if(fillsudoku(sudoku, row, col+1)){
                                return true;
                            }
                        }
                        sudoku[row][col] = 0;
                    }
                }
                return false;
            }
        }
        return true;
    }
    protected boolean flag;

    public boolean isAvailable(int sudoku[][], int row, int col, int num){
    ........
    ........
    }
}
导入java.text.DecimalFormat;
公共班机{
公共静态void main(字符串[]args){
int数独[][]={{8,0,0,0,0,0,0,0,0},
{0, 0, 3, 6, 0, 0, 0, 0, 0},
{0, 7, 0, 0, 9, 0, 2, 0, 0},
{0, 5, 0, 0, 0, 7, 0, 0, 0},
{0, 0, 0, 0, 4, 5, 7, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 3, 0},
{0, 0, 1, 0, 0, 0, 0, 6, 8},
{0, 0, 8, 5, 0, 0, 0, 1, 0},
{0, 9, 0, 0, 0, 0, 4, 0, 0}};
Main m=新的Main();
long starttime=System.nanoTime();
布尔k=m.fillsudoku(数独,0,0);
long-endtime=System.nanoTime();
DecimalFormat df=新的DecimalFormat(“#.###”);
如果(k){
System.out.println(“找到答案”);
System.out.println(“经过的时间=”+df.format((double)(endtime-starttime)/1000000)+“ms”);
对于(int i=0;i<9;i++){
对于(int j=0;j<9;j++){
System.out.print(数独[i][j]+“”);
}
System.out.println();
}
}否则{
System.out.println(“未找到”);
}
}
公共数独(整数数独[],整数行,整数列){
如果(第9行){
如果(数独[行][列]!=0){
if(col<8){
返回数独(数独,行,列+1);
}
否则,如果(第8行){
返回数独(数独,行+1,0);
}
返回true;
}
否则{

对于(inti=1;i不幸的是,这里的多线程处理不会给您带来任何好处。
与连续运行3个简单循环相比,每次方法调用创建3个线程的成本更高。
27实际上,检查和重新分配迭代不值得并行

说到改进,我们可以使用线程池重写该方法。我尝试过,结果如下:

54.25ms     // your plain version
65397.06ms  // your multithreading version
5500.82ms   // ExecutorService version
我只是将变量转换为变量,将它们传递给并调用:

Runnable r1=()->{…};
//其他跑步者
最终未来f1=执行服务。提交(r1);
//其他期货
试一试{
f1.get();
//其他得到
}捕获(执行异常){…}

您可以有效地使用线程,但不能让它们执行如此微小的工作。您正在尝试对单个字段按顺序执行多个
i
,这是进行并行化的最佳位置。请注意,您必须深度克隆
数独
数组,这样您的线程就不会相互重叠。加速速度接近CPU的数量很容易通过这种方式实现。

你可以从替换所有
标志=false;
返回false;
方法
isAvailable中所做的事情看起来很简单,我怀疑它比创建线程花费更多的时间。在这种情况下总是值得一读的:@Kapcash不,它不慢,beca使用在一个循环中创建和启动9次迭代的整个线程。其开销是惊人的(慢5000倍)。在极快的方法“isAvailable”中没有使用线程的位置,它只会减慢速度。
import java.text.DecimalFormat;

public class Main {

    public static void main(String[] args){

          int sudoku[][] = {{8, 0, 0, 0, 0, 0, 0, 0, 0},
                            {0, 0, 3, 6, 0, 0, 0, 0, 0},
                            {0, 7, 0, 0, 9, 0, 2, 0, 0},
                            {0, 5, 0, 0, 0, 7, 0, 0, 0},
                            {0, 0, 0, 0, 4, 5, 7, 0, 0},
                            {0, 0, 0, 1, 0, 0, 0, 3, 0},
                            {0, 0, 1, 0, 0, 0, 0, 6, 8},
                            {0, 0, 8, 5, 0, 0, 0, 1, 0},
                            {0, 9, 0, 0, 0, 0, 4, 0, 0}};

        Main m = new Main();
        long starttime = System.nanoTime();
        boolean k = m.fillsudoku(sudoku, 0, 0);
        long endtime = System.nanoTime();

        DecimalFormat df = new DecimalFormat("#.##");

        if (k) {
            System.out.println("Answer found");
            System.out.println("Time elapsed = " + df.format((double) (endtime - starttime) / 1000000) + "ms");
            for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    System.out.print(sudoku[i][j] + " ");
                }
                System.out.println();
            }
        } else {
            System.out.println("Not found");
        }
    }

    public boolean fillsudoku(int sudoku[][], int row, int col){
        if(row < 9){
            if(sudoku[row][col] != 0){
                if(col < 8){
                    return fillsudoku(sudoku, row, col+1);
                }
                else if(row < 8){
                    return fillsudoku(sudoku, row+1, 0);
                }
                return true;
            }
            else{
                for(int i=1;i<=9;i++){
                    if(isAvailable(sudoku, row, col, i)){        // <- checking function
                        sudoku[row][col] = i;
                        if(col == 8){
                            if(fillsudoku(sudoku, row+1, 0)){
                                return true;
                            }
                        }
                        else{
                            if(fillsudoku(sudoku, row, col+1)){
                                return true;
                            }
                        }
                        sudoku[row][col] = 0;
                    }
                }
                return false;
            }
        }
        return true;
    }
    protected boolean flag;

    public boolean isAvailable(int sudoku[][], int row, int col, int num){
    ........
    ........
    }
}
54.25ms     // your plain version
65397.06ms  // your multithreading version
5500.82ms   // ExecutorService version
Runnable r1 = () -> { ... };
// other Runnables

final Future<?> f1 = executorService.submit(r1);
// other Futures

try {
    f1.get();
    // other gets
} catch (ExecutionException e) { ... }