Java синхронизация потоков для печати матрицы (2d массив) - PullRequest
0 голосов
/ 26 апреля 2020

Здравствуйте, я пытаюсь распечатать матрицу и разделить эту работу между различными потоками.

Например, в приведенном ниже коде я попытался сделать логи c, и он отлично работает для 1 потока.

Для нескольких потоков я думаю, что мне как-то нужно синхронизировать start и end , чтобы каждый поток получал разные значения для них.

Я хочу, чтобы разные потоки печатали разные строки (в зависимости от количества потоков) этой матрицы (не имеет значения порядок), но каждый поток должен работать с уникальными строками ).

Есть идеи, как это можно сделать?

import javax.swing.plaf.TableHeaderUI;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Mythread {
    int[][] matrix;
    public Mythread(int nr){
        matrix = new int[nr][nr];
        for(int i = 0; i <nr; i++){
            for(int j = 0; j < nr; j++)
                matrix[i][j] = i;
        }
    }

    public void printMatrix(int start, int end){
        System.out.println("Start = " +start + ";thread"+Thread.currentThread().getId());
        System.out.println("End = " +end+ ";thread"+Thread.currentThread().getId());
        for(int i = start; i <end; i++){
            for(int j = 0; j < 4; j++) {
                System.out.print(matrix[i][j] + "<->");
            }
            System.out.println();
        }
    }

    public void testRun() throws InterruptedException {
        ExecutorService ex = Executors.newFixedThreadPool(1);
        for(int i=0 ; i < 4; i++) {
                final int start = i;
                final int end = i + 1;
                ex.execute(new Runnable() {
                    @Override
                    public void run() {
                        printMatrix(start, end);
                    }
                });
        }
        ex.shutdown();
        ex.awaitTermination(1, TimeUnit.MINUTES);
        System.out.println("DONE");

        /*
        works for nThreads = 1 -> for Thread Pool
        Start = 0;thread14
        End = 1;thread14
        0<->0<->0<->0<->
        Start = 1;thread14
        End = 2;thread14
        1<->1<->1<->1<->
        Start = 2;thread14
        End = 3;thread14
        2<->2<->2<->2<->
        Start = 3;thread14
        End = 4;thread14
        3<->3<->3<->3<->
        DONE
         */


    }



    public static void main(String[] args) throws InterruptedException {
        Mythread a = new Mythread(4);
        a.testRun();
    }
}

1 Ответ

1 голос
/ 27 апреля 2020

Вот простой способ достижения sh вашей цели - использовать несколько потоков для печати строк двумерного целочисленного массива в произвольном порядке:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class ConcurrentMatrixPrint {
    private int[][] matrix;
    public ConcurrentMatrixPrint(int nr){
        matrix = new int[nr][nr];
        for(int i = 0; i <nr; i++){
            for(int j = 0; j < nr; j++)
                matrix[i][j] = i;
        }
    }

    public void printRow(int row){
        //Creates a builder and initializes with the thread id and a tab
        StringBuilder sb = new StringBuilder();
        sb.append(Thread.currentThread().getId());
        sb.append("\t");

        //Loop through columns in the current row
        for(int i = 0; i < matrix[row].length; i++){
            //Add the data in the current row and column to the builder
            sb.append(matrix[row][i]);
            //This just makes the output a little nicer, only adds comma if there
            //  is another item to print so there is no trailing comma at the end.
            if(i+1 < matrix[row].length){
                sb.append(",");
            }
        }
        //Print the resulting comma separated string
        System.out.println(sb);
    }

    public void testRun() throws InterruptedException {
        //Use an atomic integer to prevent memory consistency issues
        AtomicInteger rowIndex = new AtomicInteger(0);
        ExecutorService ex = Executors.newFixedThreadPool(4);
        for(int i=0 ; i < matrix.length; i++) {
                ex.execute(new Runnable() {
                    @Override
                    public void run() {
                        //Each thread will print a row based on the value
                        // of the atomic integer and will also increment
                        // that integer.
                        printRow(rowIndex.getAndIncrement());
                    }
                });
        }
        ex.shutdown();
        ex.awaitTermination(1, TimeUnit.MINUTES);
        System.out.println("DONE");
    }

    public static void main(String[] args) throws InterruptedException {
        ConcurrentMatrixPrint a = new ConcurrentMatrixPrint(8);
        a.testRun();
    }
}

Я добавил комментарии в коде , но в основном все потоки имеют целочисленный индекс, который имеет атоми c и увеличивается с каждым новым заданием, выполняемым исполнителю.

Обратите внимание, что в выходных данных отображается идентификатор потока, который отвечал за генерацию строки текста как первое значение напечатано. Таким образом, в примере вывода ниже вы можете увидеть поток 12, напечатавший первую строку, затем поток 14, напечатавший следующую строку, и т. Д. c.

Вот пример вывода:

12  1,1,1,1,1,1,1,1
14  3,3,3,3,3,3,3,3
11  0,0,0,0,0,0,0,0
13  2,2,2,2,2,2,2,2
11  6,6,6,6,6,6,6,6
14  5,5,5,5,5,5,5,5
12  4,4,4,4,4,4,4,4
13  7,7,7,7,7,7,7,7
DONE

Надеюсь, это поможет!

...