Java Thread Design - PullRequest
       43

Java Thread Design

0 голосов
/ 13 июня 2018

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

Вот мой пример использования: основной поток создастдочерняя нить.Дочерний поток создаст два других потока (WebCallThread и RestCallThread), которые будут вызывать веб-службу REST.

Я использовал потоки здесь, поскольку для извлечения значений из вызовов REST требуется некоторое время. В основном, службы REST простовозвращает список пар.

Для простоты, я просто использовал Math.random () здесь просто для генерации кода ...

package com.thread;
import java.util.ArrayList;
import java.util.List;


public class SampleThreads {
    static List<Double> dblList = new ArrayList<Double>();
    static List<Double> statelList = new ArrayList<Double>();

    static boolean webResult = false;
    static boolean restResult = false;

    public static void main(String[] args) {
        System.out.println("Starting ThreadTesting!!!!");
        ChildThread childThread = new ChildThread();;
        childThread.start();

        try {
            childThread.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        if(webResult && restResult) {
            System.out.println("Success WebCall!!!!");
            System.out.println(dblList);
            System.out.println(statelList);
        }else {
            System.out.println("Something gone wrong!!!!!");
        }

        System.out.println("Finished ThreadTesting!!!!");
    }

    static class ChildThread extends Thread {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            System.out.println("Starting ChildThread!!!!");
            WebCallThread webThread = new WebCallThread();
            webThread.start();

            RestCallThread restThread = new RestCallThread();
            restThread.start();

            try {
                webThread.join();
                restThread.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("Finished ChildThread!!!!");
        }

    }

    static class WebCallThread extends Thread {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            System.out.println("Starting WebCallThread!!!!");
            int ctr =0;
            while(true) {
                if(ctr > 5) {
                    webResult = true;
                    System.out.println("Finished WebCallThread!!!!");
                    return;
                }
                System.out.println("Adding to WebCallThread :: " + ctr);
                dblList.add(Math.random());
                ctr++;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

    }

    static class RestCallThread extends Thread {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            System.out.println("Starting RestCallThread!!!!");
            int ctr =0;
            while(true) {
                if(ctr > 10) {
                    restResult = true;
                    System.out.println("Finished RestCallThread!!!!");
                    return;
                }
                System.out.println("Adding to RestCallThread :: " + ctr);
                statelList.add(Math.random());
                ctr++;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }

    }
}

Я немного беспокоюсь о своей проверкеесли с webResult и restResult все в порядке, или потокобезопасен. Что, если поток прерывается или происходит сбой при вызове службы REST.Так что можно предположить, что значения не будут обновлены правильно, и я могу записать «Что-то пошло не так !!!!!»сообщение?

if(webResult && restResult) {
            System.out.println("Success WebCall!!!!");
            System.out.println(dblList);
            System.out.println(statelList);
        }else {
            System.out.println("Something gone wrong!!!!!");
        }

Кроме того, я использовал переменные для хранения возвращенного результата REST в моем основном потоке, и я буду выполнять обработку результатов.Значения этих потоков заполняются моим вызовом веб-службы REST.

static List<Double> dblList = new ArrayList<Double>();
    static List<Double> statelList = new ArrayList<Double>();

Я не являюсь экспертом по Java Thread, и я только что написал это на лету.Может ли кто-нибудь придираться к моему коду и есть ли вероятность, что он может потерпеть неудачу?Я открыт для предложения по улучшению кода.

1 Ответ

0 голосов
/ 13 июня 2018

В вашей реализации есть несколько проблем, на которые я могу указать.Во-первых, использование static boolean переменных, таких как webResult, restResult, является интуитивно понятным и также подвержено ошибкам.Эти переменные читаются и записываются несколькими потоками и могут привести к условиям гонки в параллельной настройке.Вы могли бы лучше использовать механизм координации потоков, такой как CountDownLatch, чтобы достичь той же цели более элегантно.

Другой момент заключается в том, что оба ваших потока WebCallThread и RestCallThread добавляют результаты в общую структуру данных, которая используется другими потоками, такими как основной Thread.Это может привести к другому состоянию гонки.Следовательно, вы можете использовать Callable вместо Runnable здесь.

Наконец, создание нового потока для каждого запроса не является хорошей практикой, поскольку создание потока стоит дорого.Таким образом, вы можете использовать ExecutorService и совместно использовать несколько потоков из пула, чтобы преодолеть затраты, связанные с созданием ненужных потоков.

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

Улучшенный код с предложенными выше изменениями приведен ниже..

public class SampleThreads {
    private static final CountDownLatch latch = new CountDownLatch(2);
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        System.out.println("Starting ThreadTesting!!!!");

        ExecutorService executor = Executors.newFixedThreadPool(4);

        try {
            Future<List<Double>> webResponse = executor.submit(new WebCallThread());
            Future<List<Double>> restResponse = executor.submit(new RestCallThread());
            latch.await();
            System.out.println("Success WebCall!!!!");
            System.out.println(webResponse.get());
            System.out.println(restResponse.get());
            System.out.println("Finished ThreadTesting!!!!");
        } finally {
            executor.shutdown();
        }
    }

    static class WebCallThread implements Callable<List<Double>> {
        @Override
        public List<Double> call() throws Exception {
            final List<Double> dblList = new ArrayList<>();
            System.out.println("Starting WebCallThread!!!!");
            int ctr = 0;
            while (true) {
                if (ctr > 5) {
                    latch.countDown();
                    System.out.println("Finished WebCallThread!!!!");
                    return dblList;
                }
                System.out.println("Adding to WebCallThread :: " + ctr);
                dblList.add(Math.random());
                ctr++;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    static class RestCallThread implements Callable<List<Double>> {
        @Override
        public List<Double> call() throws Exception {
            List<Double> statelList = new ArrayList<>();
            System.out.println("Starting RestCallThread!!!!");
            int ctr = 0;
            while (true) {
                if (ctr > 10) {
                    latch.countDown();
                    System.out.println("Finished RestCallThread!!!!");
                    return statelList;
                }
                System.out.println("Adding to RestCallThread :: " + ctr);
                statelList.add(Math.random());
                ctr++;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}
...