Article View: pl.comp.lang.java
Article #149842Re: czy wątki mogą świadczyć usługi?
From: Waldek Kot
Date: Sun, 21 Mar 2010 23:46
Date: Sun, 21 Mar 2010 23:46
158 lines
5648 bytes
5648 bytes
On Mar 21, 5:29 pm, andrzej salwicki <salwi...@gmail.com> wrote:
> Czy można w efektywny sposób zaprogramować wątek A tak by pełnił swoje
> zadanie i równocześnie był gotów świadczyc usługi? Dokładniej, czy
> inne wątki: B, C, ... mogą wywoływać metody publiczne, synchronized
> wątku A, powodując chwilowe przerwanie akcji wątku A, wykonanie
> wskazanej metody, po czym wątek A kontynuuje swoje obliczenia.
Cześć,
Skłaniałbym się do odpowiedzi pozytywnej, ale zastanawiam się nad
użytym przez Ciebie sformułowaniem "efektywnie" (bo to -
intersubiektywnie - dosyć pojemne określenie ;-)).
Proste rozwiązanie jakie widzę to wprowadzenie do obiektu stanu
modyfikowanego poprzez wywoływanie metod publicznych obiektu i
"sterującego" tym co wykonuje się w ramach metody run(). Bo
oczywiście, wyjście z metody run() skutkuje zakończeniem wątku, więc
"wykonanie" metody obiektu też nie może tego zrobić.
Poniżej przykładowy kod, myślę, że jest dosyć oczywisty, choć zapewne
można uczynić go jeszcze bardziej efektywnym. W Java komunikowanie
wątkowi, że ma coś zrobić (np. zatrzymać się) jest kooperatywne i
zwykle zakłada, że co jakiś czas (= w określonych miejscach kodu)
wątek wykonuje sprawdzenie np. że otrzymał polecenie zatrzymania się i
sam podejmuje decyzję, co z tym zrobić. Potencjalnie, w tym moim
przykładzie, jeśli metoda domyślna (defaultMetoda) wykonywałaby się
długo, to to sprawdzenie czy tryb pracy (mode) jest inny niż domyślny
mogłoby także być wykonywane wewnątrz tej metody, przez co obiekt
szybciej zareagowałby na wykonanie innego niż domyślne zadanie (czyli
szybciej zareagowałby na wywołanie jego metody publicznej z innego
wątku)...
Możnaby też tę metodę drukujMetoda() wykonywać na oddzielnym wątku,
itd...
Przy odrobinie wysiłku (i zastosowaniu paru wzorców projektowych)
możnaby też ten kod uczynić bardziej generycznym i wymagającym mniej
modyfikacji przy dodawaniu kolejnych metod...
\\-------- SPOOLER ---------
package pl.waldekkot;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
public class Spooler extends Thread {
private enum Modes { DEFAULT, DRUKUJ };
private AtomicInteger mode = new
AtomicInteger(Modes.DEFAULT.ordinal());
private BlockingQueue<String> queueDrukuj = new
LinkedBlockingQueue<String>();
public synchronized void drukuj(String x) {
try {
this.queueDrukuj.put(x);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.mode.set(Modes.DRUKUJ.ordinal());
}
@Override
public void run() {
int i = 0;
while( true ) {
switch (Modes.values()[this.mode.get()]) {
case DRUKUJ:
try {
drukujMetoda(this.queueDrukuj.take());
} catch (InterruptedException e1) {
e1.printStackTrace();
}
this.mode.set(Modes.DEFAULT.ordinal());
break;
default:
if(this.queueDrukuj.size() > 0) {
this.mode.set(Modes.DRUKUJ.ordinal());
} else {
defaultMetoda(i);
i++;
}
break;
}
}
}
private void drukujMetoda(String x) {
System.out.println("wykonuje metode drukuj z parametrem: " + x);
}
private void defaultMetoda(int i) {
System.out.println("wykonuje metode default z parametrem: " + i);
}
}
\\-------- KLIENT ---------
package pl.waldekkot;
public class Klient extends Thread {
private Spooler s;
private String msg;
public Klient(Spooler s, String msg) {
this.s = s;
this.msg = msg;
}
@Override
public void run() {
for(int i = 0; i < 10; i++) {
this.s.drukuj(msg + " " + i);
}
}
}
\\--------- TEST ----------
package pl.waldekkot;
public class ThreadExample {
public static void main(String[] args) throws InterruptedException {
Spooler s = new Spooler();
Klient k1;
Klient k2;
s.start();
k1 = new Klient(s, "pierwszy");
k1.start();
Thread.sleep(500);
k2 = new Klient(s, "drugi");
k2.start();
Thread.sleep(500);
k1 = new Klient(s, "pierwszy znowu");
k1.start();
Thread.sleep(500);
k2 = new Klient(s, "drugi znowu");
k2.start();
Thread.sleep(5000);
}
}
Pozdrawiam,
Waldek Kot
Technical Details
Message-ID:
<5eee1b7e-e295-4861-aa8c-aa72ff0989e6@g10g2000yqh.googlegroups.com>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.gazeta.pl!newsfeed.pionier.net.pl!news.glorb.com!npeer02.iad.highwinds-media.com!news.highwinds-media.com!feed-me.highwinds-media.com!postnews.google.com!g10g2000yqh.googlegroups.com!not-for-mailReferences:
<4c3b4f20-3f62-4e54-9e3c-298e4ea6c3e5@g10g2000yqh.googlegroups.com>Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.gazeta.pl!newsfeed.pionier.net.pl!news.glorb.com!npeer02.iad.highwinds-media.com!news.highwinds-media.com!feed-me.highwinds-media.com!postnews.google.com!g10g2000yqh.googlegroups.com!not-for-mail From: Waldek Kot <waldek.kot@googlemail.com> Newsgroups: pl.comp.lang.java Subject: Re: czy wątki mogą świadczyć usługi? Date: Sun, 21 Mar 2010 16:46:43 -0700 (PDT) Organization: http://groups.google.com Lines: 168 Message-ID: <5eee1b7e-e295-4861-aa8c-aa72ff0989e6@g10g2000yqh.googlegroups.com> References: <4c3b4f20-3f62-4e54-9e3c-298e4ea6c3e5@g10g2000yqh.googlegroups.com> NNTP-Posting-Host: 217.197.168.106 Mime-Version: 1.0 X-Trace: posting.google.com 1269215203 2289 127.0.0.1 (21 Mar 2010 23:46:43 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Sun, 21 Mar 2010 23:46:43 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: g10g2000yqh.googlegroups.com; posting-host=217.197.168.106; posting-account=DVw7XwoAAAD8FwG_pqifTpvTBhZJo1Ma User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6,gzip(gfe),gzip(gfe) Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit