Wielowątkowość - Czy dobrze ją pojmuję?

Wielowątkowość - Czy dobrze ją pojmuję?
D6
  • Rejestracja:ponad 14 lat
  • Ostatnio:prawie 12 lat
  • Postów:76
0

Witam,

Otóż, posiadam problem z wywołaniem danej funkcji (wątku). Otóż nie jestem pewny czy to jest osobny wątek czy też coś robię źle. To tak, mam sobie dwie klasy, jedna to jest Timer która tworzy nowy obiekt nowej klasy przy inicjalizacji timera - tą klasą jest klasa odgrywająca dźwięki - oczywiście dziedziczy po Thread. I teraz jak utworzę sobie w tej klasie metodę która ma jeden parametr (np i) to czy to będzie działać w osobnym wątku ta metoda? To i jest potrzebne do ustalenia który rodzaj dźwięku ma być odegrany jeżeli jest np równe zero to "tik" a jeżeli równe jeden to "tok".

W Timerze wygląda to tak:

Kopiuj
 
    public void run() {
        playThisSound.run(i);
        ++i;
        if(i==metrum)
            i=0;
    }

Natomiast w klasie która dziedziczy po thread i odhrywa dźwięki tak:

Kopiuj
 
    
    public void run(int i) {
        try {
            if(i==0) {
                playTock.start();
            }
            else {
                playTick.start();
            }
        }catch(Exception ex) {}
    }
Black007
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 12 godzin
0

Cześć.
Podeślij kod całych klas.

Na pierwszy rzut oka, to jest mały błąd:

Klasa do odtwarzania muzyki nie może mieć metody run(int).
Gdyż takiej metody nie ma w Thread i nie będzie ona wywoływana wewnątrz wątku.

Rozwiązaniem powinno być utworzenie nowego obiektu Playera - przekazanie mu przez konstruktor, lub settera wartości i.
Następnie wywołanie metody start() z klasy bazowej Thread.

np.:

Kopiuj
 public class MyThread implements Runnable{

     private int i;
     
     public MyThread(int i){
        this.i = i;
      }

     public void run(){
        funckaj(i);
     }
} 

A w kodzie wywołującym:

Kopiuj

MyThread thread = new MyThread(12);
Thread starter = new Thread(thread);
starter.start();
 

"Nie popełnia błędów tylko ten, kto nic nie robi"
D6
  • Rejestracja:ponad 14 lat
  • Ostatnio:prawie 12 lat
  • Postów:76
0

Z tym tworzeniem run(int) było tak jak się obawiałem - przebudowałem trochę kod - niestety nie wykorzystałem Twojej propozycji - jednak trochę inną, bo odtwarzanie dźwięku jest cykliczne i występuje w odstępach mniej niż 1 sekunda, więc ciągłe tworzenie nowego obiektu bardzo spowalniałoby działanie aplikacji - zobaczę jak z wydajnością jest na telefonie - jeśli wszystko będzie równo to problem został rozwiązany.

Niestety - to nie do końca działa wygląda na to że wątek wykonywany jest raz. Oto kod timera i klasy grającej:

Timer:

Kopiuj
import java.util.TimerTask;

/**
 * @author Damian
 */
public class MetronomeTimerEvent extends TimerTask{        
    
    public MetronomeTimerEvent(byte metr) {
        i = 0;
        metrum = metr;
        playThis = new PlayTik();
        playThisStart = new Thread(playThis);
    }

    public void run() {
        playThisStart.start();
        i++;
        if(i==metrum)
            i=0;
    }
    
    private byte i;
    private PlayTik playThis;
    private Thread playThisStart;
    public byte metrum;
}

 

PlayTik

Kopiuj
import javax.microedition.media.control.*;
import javax.microedition.media.*;

/**
 * @author Damian
 */
public class PlayTik implements Runnable {
    
    public PlayTik() {
        try {
            playTick = Manager.createPlayer(getClass().getResourceAsStream("/1.wav"), "audio/x-wav");
            playTick.realize();
            playTick.prefetch();
        } catch(Exception ex) { }
        VolumeControl volumeV = (VolumeControl)playTick.getControl("VolumeControl");
        volumeV.setLevel(99);
        try {
            playTock = Manager.createPlayer(getClass().getResourceAsStream("/2.wav"), "audio/x-wav");
            playTock.realize();
            playTock.prefetch();
        } catch(Exception ex) { }
        VolumeControl volumeV1 = (VolumeControl)playTock.getControl("VolumeControl");
        volumeV1.setLevel(99);
    }
    
    public void run() {
            try {
                if(i==0) {
                    playTock.start();
                }
                else {
                    playTick.start();
                }
            }catch(Exception ex) {}
    }
    
    public void changeVariableI(byte changedVariable) {
        i = changedVariable;
    }
    
    public byte i;
    private Player playTick;
    private Player playTock;
}

 
edytowany 1x, ostatnio: dejmien666
Black007
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 12 godzin
0

Cześć.
Pomoże Ci klasa java.util.Timer i jej metoda schedule(TimerTask task, Date firstTime, long period)

W ten sposób ustawisz co ile ma się wykonywać TimerTask.


"Nie popełnia błędów tylko ten, kto nic nie robi"
edytowany 1x, ostatnio: Black007
D6
  • Rejestracja:ponad 14 lat
  • Ostatnio:prawie 12 lat
  • Postów:76
0

Dam pozostałe klasy dla pewności, bo właśnie to co podałem - to jest klasa z timerem wystartowanym który działa z częstotliwością obliczoną na podstawie podanej ilości bpm przez użytkownika.

Klasa główna:

Kopiuj
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

/**
 * @author Damian
 */
public class Main extends MIDlet implements CommandListener {
    
    public Main() {
        design = new InterfaceDesign();
        Command exit = new Command("Koniec", Command.EXIT, 0);
        design.addCommand(exit);
        startButton = new Command("Start/Stop", Command.OK, 0);
        design.addCommand(startButton);
        design.setCommandListener(this);
        Display mobileDisplay = Display.getDisplay(this);
        mobileDisplay.setCurrent(design);
        
    }

    public void startApp() {
    }
    
    public void pauseApp() {
    }
    
    public void destroyApp(boolean unconditional) {
    }
    
    public void commandAction(Command c, Displayable s) {
        if(c.getCommandType() == Command.EXIT)
            notifyDestroyed();
        
        if(c.getCommandType() == Command.OK) {
            design.changeState();
        }
    }
    
    private InterfaceDesign design;
    private Command startButton;
}

 

Klasa w której startuje timer, rysuje gui i takie tam.

Kopiuj
import javax.microedition.lcdui.*;
import java.util.Timer;

/**
 * @author Damian
 */
public class InterfaceDesign extends Canvas implements CommandListener {

    /**
     * constructor
     */
    public InterfaceDesign() {
        metronomState = "Start";
        isWorking = Boolean.FALSE;
        bpmString = "90";
        howManyBpm = 90;
        calculateInterval = 60000/(howManyBpm);
        timer = new Timer();
        metrum = 3;
        metrumString = "3";
        try {
            // Set up this canvas to listen to command events
            setCommandListener(this);
            // Add the Exit command
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * paint
     */
    public void paint(Graphics g) {
        Font f1 = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_LARGE);  
        Font f2 = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);  
        Font f3 = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
        g.setColor(255, 255, 255);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(0, 0, 0);
        g.drawString(metronomState, getWidth()/2, getHeight()/2, Graphics.TOP | Graphics.LEFT);
        g.drawString("BPM: " + bpmString, getWidth()/2, (getHeight()/2)-20, Graphics.TOP | Graphics.LEFT);
        g.drawString("Metrum: " + metrumString, getWidth()/2, (getHeight()/2)-40, Graphics.TOP | Graphics.LEFT);
        g.drawString("Metronom v3.0\nDamian Smilgin(C)", 0, 0, Graphics.TOP | Graphics.LEFT);
    }

    /**
     * Called when a key is pressed.
     */
    protected void keyPressed(int keyCode) {
        if(keyCode == -5) {
            changeState();
            repaint();
        }
        else if(keyCode == -1 && isWorking == Boolean.FALSE) {
            howManyBpm++;
            bpmString = Integer.toString(howManyBpm);
            repaint();
        }
        else if(keyCode == -2 && isWorking == Boolean.FALSE) {
            howManyBpm--;
            bpmString = Integer.toString(howManyBpm);
            repaint();
        }
        else if((keyCode == -4) && (isWorking == Boolean.FALSE)) {
            metrum++;
            metrumString = Integer.toString(metrum);
            repaint();
        }
        else if((keyCode == -3) && (isWorking == Boolean.FALSE) && (metrum > 2)) {
            metrum--;
            metrumString = Integer.toString(metrum);
            repaint();
        }
    }
    
    public void changeState() {
        if(isWorking == Boolean.FALSE) {
            isWorking = Boolean.TRUE;
            metronomState = "Stop";
            startMetronome();
        }
        else if(isWorking == Boolean.TRUE) {
            isWorking = Boolean.FALSE;
            metronomState = "Start";
            stopMetronome();
        }
        repaint();
    }
    
    protected void startMetronome() {
        calculateInterval = 60000/(howManyBpm);
        startTimerEvents = new MetronomeTimerEvent(metrum);
        timer.schedule(startTimerEvents, 1000, calculateInterval);
        
    }
    
    protected void stopMetronome() {
        startTimerEvents.cancel();
    }

    /**
     * Called when a key is released.
     */
    protected void keyReleased(int keyCode) {
    }

    /**
     * Called when a key is repeated (held down).
     */
    protected void keyRepeated(int keyCode) {
    }

    /**
     * Called when the pointer is dragged.
     */
    protected void pointerDragged(int x, int y) {
    }

    /**
     * Called when the pointer is pressed.
     */
    protected void pointerPressed(int x, int y) {
    }

    /**
     * Called when the pointer is released.
     */
    protected void pointerReleased(int x, int y) {
    }

    /**
     * Called when action should be handled
     */
    public void commandAction(Command command, Displayable displayable) {
    }
    
    private String metronomState;
    public Boolean isWorking;
    private int howManyBpm;
    private String bpmString;
    private int calculateInterval;
    private Timer timer;
    private MetronomeTimerEvent startTimerEvents;
    public byte metrum;
    public String metrumString;
}

 

Więc nie bardzo wiem jak dodać ten drugi timer w istniejącym już timerTask i jeszcze by działał cyklicznie.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)