Java scheduledthreadpoolexecutor, wstrzymywanie pojedynczych wątków

0

Witam
Mam taki problem. Używam klasy scheduledthreadpoolexecutor i tworzę cykliczne wątki za pomocą metody "scheduleAtFixedRate", potrzebuję te wątki zablokować na jakiś czas lub wymaga tego logika programu, aby wątek wykonywany cyklicznie został wstrzymany na parę sekund. Używam klasy "Semaphore", która posiada metodę to blokowania wątku "acquire", następnie w innym wątku wywołuje metodę "release" która odblokowuję wątek. Problem polega na tym że nie blokuję pojedynczego wątku tylko wszystkie wątki należycie do "scheduledthreadpoolexecutor" , a nie widzę powodu do tworzenia co wątek nowej instancji tej klasy, za dużo nie potrzebnego kodu. Czy są jakieś inne patenty dla chwilowe zatrzymanie wątku ?

1

nie widzę powodu do tworzenia co wątek nowej instancji tej klasy, za dużo nie potrzebnego kodu

Jeśli twój kod wygląda tak, że masz jeden semafor i wiele tasków to się nie dziw, że wszystkie zostaną zablokowane gdy go przestawisz. To tak z plażą i flagą ostrzegawczą - jeśli jest jedna to będzie ona biała/czerwona dla wszystkich plażowiczów.

Ale po kolei:

  • napisz, co chcesz osiągnąć (po co ci blokowanie tych wątków)
  • pokaż kod
2

+1

potrzebuję te wątki zablokować na jakiś czas lub wymaga tego logika programu, aby wątek wykonywany cyklicznie został wstrzymany na parę sekund.

Blokowanie wątków jest dziwne i może powodować problemy/awarie (możesz całkowicie wysycić pule wątków, na którym odpalane są te „joby”). Skąd takie wymaganie? Co chcesz zrobić?

0

@Charles_Ray: Zrobiłem bota do gry który śledzi pixele i w zależności co będzie się wyświetlało to program za pomocą klasy robot symuluję kliknięcia oraz naciśnięte klawisze. Wszystko mam już gotowe, prócz logiki która to ogarnie. Sprawdzam czy okienko w grze pojawiło się za pomocą pixeli. Wygląda to tak :
Jeśli okienko jest widoczne to : wątek "A" ma oscylować co 50ms (wykonuję się tam coś, do momentu aż okienko nie zniknie).
jeśli okienko nie jest już widoczne to : Uruchamia wątek "B" (działa co 500ms) dopóki nie pojawi się znowu okienko

do tego dochodzą jeszcze 3 wątki. Potrzebuję jakiś patent na wstrzymywanie chwilowe wątków, chyba że znacie inny patent. Tworzenie wątku za każdym razem, to nie będzie zapełniało pamięci ?

1

Mam taki problem. Używam klasy scheduledthreadpoolexecutor i tworzę cykliczne wątki za pomocą metody "scheduleAtFixedRate",

Technicznie rzecz biorąc nie tworzysz wątku tylko korzystasz z puli wątków.

Jeśli okienko jest widoczne to : wątek "A" ma oscylować co 50ms (wykonuję się tam coś, do momentu aż okienko nie zniknie).

Tzn jak okno jest widoczne to task A ma się wykonać i ponownie wykonać za 50 ms?

0

@scibi_92: musi to być zrobione wątkach bo kliknięcia i wciśnięcia klawiszy będą opóźnione

0

musi to być zrobione wątkach

A ja powiedziałem że nie ma nie być w wątkach? Po prostu moim zdaniem mylisz Runnable z wątkiem, a to nie to samo. Kiedy wykorzystujesz np. tą metodę:
https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/concurrent/ScheduledExecutorService.html#schedule(java.lang.Runnable,long,java.util.concurrent.TimeUnit) to nie tworzysz nowego wątku na ogół, tylko wykorzystujesz pulę istniejących.

No i dalej nie wyjaśniłeś:

Jeśli okienko jest widoczne to : wątek "A" ma oscylować co 50ms (wykonuję się tam coś, do momentu aż okienko nie zniknie).

Co to znaczy oscylować? Tzn że jeśli okienko jest widoczne to task A ma się wykonać i za 50 ms ponownie się wykonać? Rozumiem że A to jest po prostu coś krótkiego?

0

@scibi_92: tak, dokładnie, co 50 ms cały czas jest wykonywana jedna procedura i tak sama, m.in w niej jest zawarte to że jeśli coś znajdzie analizując pixele to ma kliknąć w to, tutaj jest opóźnienie (sleep)

0

No to możesz przekazać do niej w konstruktorze ten ScheduledExecutorService i zrobić coś w stylu:


public class TaskOne implements Runnable {
     
    private final ScheduledExecutorService executor;
     
    public TaskOne(ScheduledExecutorService executor) {
        this.executor = executor;
    } 
   
    public void run() {
        if (condition) {
            executor.schedule(new TaskTwo(), 300, TimeUnit.MICROSECONDS)
        }
    }
 }     

Ale najlepiej jak pokażesz więcej kodu

0

@scibi_92:

Pisane na szybko, dlatego tka to wygląda, dużo class wewnętrzych, jeszcze są inne klasy ale tutaj wykonuję się ten kod odpowiedzialny za włączanie wątków

import javax.swing.*;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.util.Map;
import java.util.concurrent.*;

public class PanelWyswietlania extends JPanel {
    private FramePointer framePointer;
    private BufferedImage bufferedImage;
    private Robot robot;
    private Rectangle rectCute;

    private Rectangle rectFish = new Rectangle();
    private boolean blockCliked = false;
    private int pixels[];
    private boolean running = true;

    private Thread thread;
    private Test test;

    private ConcurrentHashMap<Point, Integer> pixelsWindowsFish = new ConcurrentHashMap<>();

    private int indexSlotFish = 0;

    private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;

    public PanelWyswietlania(Test test) {
        this.test = test;
        rectCute = new Rectangle();
        try {
            robot = new Robot();
        } catch (AWTException e) {
            e.printStackTrace();
        }
        setBackground(Color.LIGHT_GRAY);
    }
    private Semaphore gateFishFind;
    private Semaphore gateCheckIsWindowFish;
    private Semaphore gateThrowRowFish;

    public void start() {
        scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(5);
        scheduledThreadPoolExecutor.scheduleAtFixedRate(new TimerTitle(), 0,1000, TimeUnit.MILLISECONDS);
        scheduledThreadPoolExecutor.scheduleAtFixedRate(new FindFish(), 0,10, TimeUnit.MILLISECONDS);
        scheduledThreadPoolExecutor.scheduleAtFixedRate(new CheckIsWindowFish(), 0,2, TimeUnit.MILLISECONDS);
        scheduledThreadPoolExecutor.scheduleAtFixedRate(new ThrowRowFish(), 0,1000, TimeUnit.MILLISECONDS);

        scheduledThreadPoolExecutor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                repaint();
            }
        }, 500, 1000/30, TimeUnit.MILLISECONDS);

        gateFishFind = new Semaphore(0);
        gateCheckIsWindowFish = new Semaphore(0);
        gateThrowRowFish = new Semaphore(0);


    }
    public synchronized void stop() {
        scheduledThreadPoolExecutor.shutdownNow();

        bufferedImage = null;
        repaint();
        System.out.println("Zatrzymano wątek");
        System.gc();System.runFinalization();
    }
    private class FindFish implements Runnable {
        @Override
        public void run() {
            if(searchFish()) {
                if(!blockCliked) {
                    robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
                    robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
                    blockCliked = true;
                    scheduledThreadPoolExecutor.schedule(new Runnable() {
                        @Override
                        public void run() {
                            blockCliked = false;
                        }
                    },300, TimeUnit.MILLISECONDS);
                }
            }
        }
    }
    private class CheckIsWindowFish implements Runnable {
        @Override
        public void run() {

        }
    }
    private class ThrowRowFish implements Runnable {
        @Override
        public void run() {
            throwFishingRod();
        }
    }
    private class TimerTitle implements Runnable {
        long timeSecunds = 0;
        long timeMinuts = 0;

        @Override
        public void run() {
            if(timeSecunds > 59) {
                timeMinuts++;
                timeSecunds = 0;
            }

            if(timeMinuts > 0) {
                test.setTitle("Fish bot : time running - " + timeMinuts + " minuts " + timeSecunds + " secunds.");
            }
            else {
                test.setTitle("Fish bot : time running - " + timeSecunds + " secunds.");
            }
            timeSecunds++;
        }
    }


    private boolean searchFish() {
        //Update area
        rectCute.setFrame(framePointer.getCenterPoint().x,framePointer.getCenterPoint().y,framePointer.getRadius(),framePointer.getRadius());
        bufferedImage = robot.createScreenCapture(rectCute);
        pixels = ((DataBufferInt) bufferedImage.getRaster().getDataBuffer()).getData();

        //0x37597C // 36587C
        //System.out.println(Integer.decode("0x37597C"));
        //if(r.getRed() > 52 && r.getRed() < 55 && r.getGreen() >85 &&r.getGreen() < 95 && r.getBlue() >115 &&r.getBlue() < 125)

        rectFish.setFrame(0,0,0,0);
        for(int i = 0; i < pixels.length; i++) {
            Color r = Color.decode(String.valueOf(pixels[i]));
            if(r.getRed() > 45 && r.getRed() < 70 && r.getGreen() >80 &&r.getGreen() < 115 && r.getBlue() >100 &&r.getBlue() < 140) {
                int size = bufferedImage.getWidth();
                robot.mouseMove(framePointer.getCenterPoint().x + i - i/size*size +2, framePointer.getCenterPoint().y + i/size +5);
                if(Trygonometria.checkCollision(framePointer.getCenterPoint().x + i - i/size*size +2, framePointer.getCenterPoint().y + i/size +5,1, framePointer.getCenterPoint().x, framePointer.getCenterPoint().y, framePointer.getRadius())) {
                    rectFish.setFrame(i - i/size*size +(getWidth()/2 - size/2) +2,i/size -2,10,10);
                    return true;
                }
            }
        }
        return false;
    }

    private boolean isWindowFishVisible() {
        rectCute.setFrame(framePointer.getCenterPoint().x,framePointer.getCenterPoint().y,framePointer.getRadius(),framePointer.getRadius());
        bufferedImage = robot.createScreenCapture(rectCute);
        pixels = ((DataBufferInt) bufferedImage.getRaster().getDataBuffer()).getData();

        boolean windowsShow = false;
        for (Map.Entry<Point, Integer> maps : pixelsWindowsFish.entrySet()) {
            if(pixels[(int)(maps.getKey().getX() + maps.getKey().getY() * bufferedImage.getWidth())] == maps.getValue()) {
                windowsShow = true;
            }
        }
        return windowsShow;
    }
    private void throwFishingRod() {
        boolean[] keys = test.getChosenKeys();
        int key = 0;
        if(indexSlotFish >= 7) {
            indexSlotFish = 0;
        }
        for(int i = indexSlotFish; i < keys.length; i++) {
            if(keys[i] == true) {
                switch(i) {
                    case 0 : key = KeyEvent.VK_1; break;
                    case 1 : key = KeyEvent.VK_2; break;
                    case 2 : key = KeyEvent.VK_3; break;
                    case 3 : key = KeyEvent.VK_4; break;
                    case 4 : key = KeyEvent.VK_F1; break;
                    case 5 : key = KeyEvent.VK_F2; break;
                    case 6 : key = KeyEvent.VK_F3; break;
                    case 7 : key = KeyEvent.VK_F4; break;
                }
                robot.keyPress(key);
                robot.keyRelease(key);


                robot.keyPress(KeyEvent.VK_SPACE);
                robot.keyRelease(KeyEvent.VK_SPACE);

                System.out.println(key);
                indexSlotFish++;
                return;
            }
            else {
                indexSlotFish++;
            }
        }
    }

    public void getPixelColorFromWindowFish() {
        rectCute.setFrame(framePointer.getCenterPoint().x,framePointer.getCenterPoint().y,framePointer.getRadius(),framePointer.getRadius());
        bufferedImage = robot.createScreenCapture(rectCute);
        pixels = ((DataBufferInt) bufferedImage.getRaster().getDataBuffer()).getData();

        pixelsWindowsFish.clear();
        System.gc();System.runFinalization();

        pixelsWindowsFish.put(new Point(bufferedImage.getWidth()/10, bufferedImage.getHeight()/2), pixels[bufferedImage.getWidth()/10 + bufferedImage.getHeight()/2 * bufferedImage.getWidth()]);
        pixelsWindowsFish.put(new Point(bufferedImage.getWidth()/2, bufferedImage.getHeight()/10), pixels[bufferedImage.getWidth()/2 + bufferedImage.getHeight()/10 * bufferedImage.getWidth()]);
        pixelsWindowsFish.put(new Point(bufferedImage.getWidth()/2, bufferedImage.getHeight()/2), pixels[bufferedImage.getWidth()/2 + bufferedImage.getHeight()/2 * bufferedImage.getWidth()]);
        pixelsWindowsFish.put(new Point(bufferedImage.getWidth()/2, (int)(bufferedImage.getHeight()*0.9)), pixels[bufferedImage.getWidth()/2 + (int)(bufferedImage.getHeight()*0.9) * bufferedImage.getWidth()]);
        pixelsWindowsFish.put(new Point((int)(bufferedImage.getWidth()*0.9), bufferedImage.getHeight()/2), pixels[(int)(bufferedImage.getWidth()*0.9) + bufferedImage.getHeight()/2 * bufferedImage.getWidth()]);
        System.out.println("pobrano wartosic kolorow :  " + pixelsWindowsFish.size());
    }


    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;

        if(bufferedImage !=null) {
            g2.drawImage(bufferedImage, getWidth() / 2 - bufferedImage.getWidth() / 2, 0, null);
            if (blockCliked) {
                g2.setPaint(Color.RED);
            } else {
                g2.setPaint(Color.GREEN);
            }
            g2.draw(rectFish);

            for (Map.Entry<Point, Integer> maps : pixelsWindowsFish.entrySet()) {
                g2.setPaint(Color.decode(String.valueOf(maps.getValue())));
                g2.setPaint(Color.RED);
                g2.drawRect(getWidth() / 2 + bufferedImage.getWidth() / 2 - maps.getKey().x, maps.getKey().y, 2, 2);
            }
        }
    }

    public void setFramePointer(FramePointer framePointer) {this.framePointer = framePointer;}
}
1

Nie wczytywałem się w kod, ale może zrobić zwykły polling? Odpalasz jednego taska co np. 10ms i sprawdzasz po kolei, które operacje są do wykonania. Mogą być wtedy jałowe przebiegi jak przy pollingu, ale nie robisz dziwnej logiki reschedulowania i blokowania. Pseudokod:

while(true) {
   if(mogęRobić()) rób();
   timeout(10ms);
}

Jeżeli operacje są blokujące, to możesz je wrzucać jako zadania na jakaś kolejkę, która ogarnie Ci już wtedy N workerów.

0

@Charles_Ray: nie da rady tak

0

@Charles_Ray: Pojawia się okienko i usypiam ten wątek na 2 sekundy, ale po upływie 1 sekundy wyskakuję okienko i tamten wątek pomimo że if(jezeli jest okienko widoczne ) to sleep spowoduję wykonanie się tej instrukcji później. Jak moge wyłączyć wątek kiedy jest w stanie "sleep" ?

0

Po co masz usypiać jakiś wątek na 2 sekundy, skoro w ciągu tych 2 sekund możesz sprawdzić 1000 razy czy okienko jest aktywne i jeśli tak, to coś tam kliknąć. Spróbuj pomyśleć w kategorii event loop, a nie blokowania wątków.

1 użytkowników online, w tym zalogowanych: 0, gości: 1