मैंने जो प्रोजेक्ट बना रहा हूं उसके लिए मैंने मल्टीथ्रेडिंग की कोशिश की। प्रोजेक्ट में मुझे हर बार एक निश्चित फ़ंक्शन के लिए कॉल करने पर कई बार एक निश्चित गणना करने की आवश्यकता होती है। मैंने इसे कैसे करना है यह समझने के लिए कुछ परीक्षण कोड बनाने की कोशिश की, लेकिन मैं इसे ठीक से काम नहीं कर सकता (जब मैं इसे डीबग करता हूं तो कोड पूरी तरह से काम करता है, लेकिन अगर मैं इसे सामान्य रूप से चलाता हूं तो यह पहले चक्र से पहले काम नहीं करता है )

कोड में एक अंतहीन लूप है जो मेरे प्रोजेक्ट की कॉलिंग को कई बार फ़ंक्शन के लिए नकल करता है। मैंने इसे करने की कोशिश की ताकि चेंजफ्लैग सत्य होने पर थ्रेड चलता है, और गणना के प्रत्येक भाग के बाद ध्वज को झूठा में बदल देता है ताकि यह बार-बार इसकी गणना करने से रोक सके, और फ़ंक्शन को "कॉल करने" के बाद मैं इसे सही में बदल देता हूं वापस , इसलिए यह फिर से गणना करने में सक्षम होगा।

मेरा कोड निम्नलिखित है:

import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<Result> queue = new SynchronousQueue<>();
        int loops = 0;
        MyThread[] arr = new MyThread[10];
        ArrayList<Result> ress = new ArrayList<>();

        for (int i = 0; i < arr.length; i++) {
            arr[i] = new MyThread(i, queue);
            arr[i].start();
        }
        while (true) {
            System.out.println(loops++);
            while (ress.size() < arr.length){
                ress.add(queue.take());
            }
            while (!ress.isEmpty()){
                arr[ress.get(0).getSign()].setChangeflag(true);
                ress.remove(0);
            }
        }
    }
}

import java.util.Random;
import java.util.concurrent.BlockingQueue;

public class MyThread extends Thread{
    private boolean changeflag = true;
    private boolean runflag = true;
    private int sign;
    private BlockingQueue<Result> queue;
    Random rnd = new Random();

    public MyThread(int sign, BlockingQueue<Result> queue){
        this.sign = sign;
        this.queue = queue;
    }

    public void run(){
        while (runflag){
            if(changeflag){
                changeflag = false;
                try {
                    queue.put(sense());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public Result sense(){
        return new Result( rnd.nextInt(10), sign);
    }

    public synchronized void setChangeflag(boolean changeflag) {
        this.changeflag = changeflag;
    }
}
public class Result {
    private double res;
    private int sign;

    public Result(double res, int sign) {
        this.res = res;
        this.sign = sign;
    }

    public int getSign() {
        return sign;
    }
}
0
KarshE69 28 मार्च 2020, 00:57
1
"जब मैं इसे डीबग करता हूं तो कोड पूरी तरह से काम करता प्रतीत होता है, लेकिन अगर मैं इसे सामान्य रूप से चलाता हूं तो यह पहले चक्र से पहले काम नहीं करता है" समेकन में आपका स्वागत है! मुझे समझ में नहीं आता कि आप इस कोड के साथ क्या हासिल करने की कोशिश कर रहे हैं। क्या आप समझा सकते हैं कि इसके बजाय आपका लक्ष्य क्या है? आप अपने परिणाम की गणना करने के लिए थ्रेड क्यों नहीं चलाते (या थ्रेड पूल का उपयोग करें)?
 – 
m0skit0
28 मार्च 2020, 01:14
मैं इसे बनाने की कोशिश कर रहा हूं ताकि हर बार एक निश्चित फ़ंक्शन कहा जा सके, मुझे परिणामों का एक नया सेट मिल जाएगा। मेरे वास्तविक कोड में, अर्थ() एक यादृच्छिक संख्या नहीं लौटाता है, लेकिन एक निश्चित गणना करता है, और मैं इसे उस गणना में नहीं चाहता जब तक कि सामान बदल न जाए। @m0skit0
 – 
KarshE69
28 मार्च 2020, 01:55
मुझे लगता है कि आपको मेरे उत्तर की सूचना नहीं मिली। इसलिए मैं आपको फिर से पिंग करने की कोशिश कर रहा हूं। आपकी मदद के लिए बहुत शुक्रिया!
 – 
KarshE69
28 मार्च 2020, 19:13
मुझे यह पहली बार मिला लेकिन उत्तर देना भूल गया, क्षमा करें। यदि आप यही चाहते हैं, तो आपकी रन() विधि में थोड़ी देर के लिए क्या उपयोग है? आप वहां लूप क्यों करना चाहते हैं? एक अवरुद्ध कतार भी क्यों है?
 – 
m0skit0
28 मार्च 2020, 22:49
इस तरह मेरे दोस्त ने इसे करने का सुझाव दिया। मैं मूल रूप से धागे को चालू रखता हूं लेकिन जब मैं उक्त फ़ंक्शन को कॉल करता हूं तो चेंजफ्लैग को बदल देता हूं ताकि यह गणना फिर से चलाए। और अवरुद्ध कतार इसलिए है कि मुख्य धागा तब तक प्रतीक्षा करेगा जब तक कि सभी गणनाएं तब तक जारी न हों जब तक कि यह जारी न हो जाए। यदि आपके पास ऐसा करने का बेहतर सुझाव है, तो सभी कानों में! जैसा मैंने कहा, मैं धागों के लिए नया हूं और इसी तरह मेरे मित्र ने मुझे ऐसा करने का सुझाव दिया। @m0skit0
 – 
KarshE69
29 मार्च 2020, 00:01

2 जवाब

मैं Executors.newCachedThreadPool(). यह एक ExecutorService< लौटाएगा /a> जिसका उपयोग आप submit(Callable), जो एक Future जिस पर आप अपनी इच्छानुसार ब्लॉक कर सकते हैं। यदि आप कई कार्यों को कतारबद्ध करते हैं तो आप आवश्यकतानुसार Future की सूची रख सकते हैं या कार्यों की एक सूची फिर उन्हें ExecutorService पर सबमिट करें।

यह भी नोट करें आमतौर पर इसे थ्रेड से विस्तारित करने की अनुशंसा नहीं की जाती है

उम्मीद है ये मदद करेगा!

0
m0skit0 29 मार्च 2020, 03:36

पृष्ठभूमि में sense विधि के पूरा होने की प्रतीक्षा करते हुए, केवल एक ही कारण है कि मैं, कम से कम, देख सकता हूं कि आपको Thread की आवश्यकता क्यों है, अन्य कार्य करना है। उदाहरण के लिए कुछ ग्राफिक्स प्रस्तुत करें या उपयोगकर्ता के साथ बातचीत करें।

यदि आपके मुख्य Thread को प्रत्येक अनुरोध के लिए सभी sense कार्य पूर्ण होने तक प्रतीक्षा करने की आवश्यकता है, तो आपको Threads की आवश्यकता नहीं है। विधि sense को सीधे मुख्य Thread में कॉल करें।

दूसरी ओर, यदि आपको एक पृष्ठभूमि Thread sense नौकरी करने की आवश्यकता है, जबकि मुख्य Thread अन्य कार्य कर रहा है, तो आपको दो Threads की आवश्यकता होगी: एक है मुख्य, और दूसरा पृष्ठभूमि-नौकरी है। तब आपको शायद एक निर्माता-उपभोक्ता पैटर्न की आवश्यकता होती है, जहां निर्माता (मुख्य Thread) अनुरोध बनाता है और उपभोक्ता (पृष्ठभूमि Thread) sense विधि निष्पादित करता है। लेकिन फिर ऐसा लगता है कि भूमिकाएं फिर से बदल गई हैं जैसे आप मुख्य Thread में सभी अनुरोधों को सबमिट करने के बाद पूरा करने के लिए प्रतीक्षा करना चाहते हैं। अगर ऐसा है तो आप सभी MyThreads शुरू कर सकते हैं और फिर join को कॉल कर सकते हैं जब आप उनके परिणामों की प्रतीक्षा करने के लिए तैयार हों। उदाहरण के लिए:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;

public class Main {

    public static class Result {
        private final int index;
        private final Object value;

        public Result(final int index,
                      final Object value) {
            this.index = index;
            this.value = value;
        }

        public int getIndex() {
            return index;
        }

        public Object getValue() {
            return value;
        }
    }

    public static class MyRunnable implements Runnable {
        private final int index;
        private final Collection<Result> sharedResults;

        public MyRunnable(final int index,
                          final Collection<Result> sharedResults) {
            this.index = index;
            this.sharedResults = Objects.requireNonNull(sharedResults);
        }

        @Override
        public void run() {
            final Result res = sense(); //Calculating outside the synchronized block.
            synchronized (sharedResults) { //Synchronizing, because the actual instance of this collection might not be synchronized.
                sharedResults.add(res);
            }
        }

        private Result sense() {
            return new Result(index, "Value" + index);
        }
    }

    public static void main(final String[] args) {
        final Thread[] t = new Thread[10];
        final Collection<Result> sharedResults = new ArrayList<>();

        for (int i = 0; i < t.length; ++i) {
            t[i] = new Thread(new MyRunnable(i, sharedResults));
            t[i].start();
        }

        for (final Thread thread: t)
            try { thread.join(); } catch (final InterruptedException ix) { ix.printStackTrace(); }

        sharedResults.forEach(res -> System.out.println("Result " + res.getIndex() + " with value \"" + res.getValue() + "\"."));
    }
}

दूसरा तरीका है ExecutorService जैसे @m0skit0 द्वारा सुझाए गए का उपयोग करना और परिणामों की प्रतीक्षा करने के लिए लौटाई गई Future वस्तुओं का उपयोग करना।

0
gthanop 4 अप्रैल 2020, 19:12