Article View: pl.comp.lang.java
Article #149856Re: czy wątki mogą świadczyć usługi?
From: keef
Date: Fri, 26 Mar 2010 14:28
Date: Fri, 26 Mar 2010 14:28
125 lines
6842 bytes
6842 bytes
W dniu 2010-03-25 22:39, Witold Szczerba pisze:
> On Mar 25, 5:38 pm, keef<a...@a.com> wrote:
>> Teraz pytanie:
>> Jeśli wątek jest 'pracownikiem', który może zostać całkowicie ukryty -
>> klasa używająca obiektu nawet nie musi wiedzieć, że za interfejsem chowa
>> się wątek - to czy dobrze jest go 'łączyć' na stałe z klasą, w taki
>> sposób, aby WSZYSCY widzieli, że tam jest osobny wątek?
>
> Dobrze kombinujesz, to nie jest dobry pomysł, aby cokolwiek
> dziedziczyć bez powodu.
>
>> O co mi chodzi?
>>
>> Dlaczego pisać "extends Thread" lub nawet (w publicznej klasie)
>> "implements Runnable", kiedy jest to szczegół implementacyjny, o którym
>> klienci mogą nie wiedzieć?
>
> Zauważ, że można zrobić "...extends Thread implements Cośtam..." i
> dalej w świat "puścić" ten obiekt jako Cośtam. Nikt nie musi wiedzieć,
> że to dziedziczy po Thread, będzie widać tylko metodę/metody z
> Cośtam.
Chyba powiedziałeś dokładnie to samo co ja...
Pójdę nawet dalej:
public interface AaaFactory{
public Aaa getAaa();
}
public interface Aaa{
public void sort(int[] tab);
}
public class ThreadedAaaFactory{
public Aaa getAaa(){
return new ThreadedAaa();
}
private static class ThreadedAaa implements Aaa(){
public void sort(int[] tab){
//sortuje;
}
}
public static void main(String[] args){
AaaFactory aaaFactory = new ThreadedAaa();
Aaa aaa = aaaFactory.getAaa();
}
I nie możesz polegać na tym, że to będzie w osobnym wątku, lub nie... Bo
nigdy nie wiesz czy obiekt, który dostaniesz z fabryki używa wątku, czy
nie... Implementacja jest kompletnie schowana za interfejsem Aaa i za
fabryką (która dostarcza implementacje).
>
>> Na poparcie moich wypocin, mogę przedstawić interfejs(y):
>> 1. Executor (i ExecutorService), których zadaniem jest ukrywanie wątków
>
> Ich zadaniem nie jest ukrycie wątków tylko odseparowanie spraw
> związanaych z uruchamianiem wątków, zarządzeniem pulami wątków itp.
> sprawami, a implementacją logiki, która będzie w tych wątkach
> odpalana.
Czy aby na pewno? A dlaczego nie zrobić w Aaa factory grupowania
obiektów (poolowania) za pomocą Executora? I zamiast zwracać zawsze "new
ThreadedAaa()" pobierać obiekt z puli (oczywiście trzeba rozszerzyć
interfejs Aaa). I wtedy sposób działania znów jest schowany? A co z
implementacją, gdy wiele obiektów korzysta z tego samego wątku
(kolejka)? Również klienty klasy Aaa nie muszą tego wiedzieć. Interfejs
mówi CO, a nie JAK. Jeśli wybraliśmy taką implementacje, to będzie nam
to w określony sposób działać (ale zawsze będzie robić to samo)...
>
>> 2. Interfejs Runnable, który powinien być używany ZAMIAST dziedziczenia
>> po klasie Thread (próba rozdzielenia implementacji od specyfikacji)
>
> Runnable nie powstał tylko po to, stosuje się go w wielu wielu wielu
> miejscach, łącznie z tymi, które sam w swoim programie człowiek pisze
> i od czasu gdy potrzebuje np. opakować metodę w obiekt, żeby można ją
> było przekazać jako parametr.
Po co takie sztuczki ? :P Czy nie łatwiej jest powiedzieć CO (interfejs)
ma robić i zaznaczyć, że WSZYSTKIE IMPLEMENTACJE MUSZĄ UWZGLĘDNIAĆ
WIELOWĄTKOWOŚĆ? Pytanie brzmi - po co tak robić? Jeśli nie korzystasz z
ogólnie przyjętych wzorców do synchronizacji wątków
(producent-konsument, czytanie-pisanie, etc) to pakujesz się w problemy.
I kolejne pytanie - po co informować klientów klasy, że muszą pamiętać o
wielowątkowości? Nie lepiej ją schować za implementację (ukryć i
wystawić interfejs)?
>
>> I teraz dochodzimy do zasadniczej kwestii. Jak wydzielić interfejs,
>> który przedstawia postawiony problem w sposób niezależny od wątków? Da
>> się? A jak się nie da, to pytanie brzmi dlaczego? Być może problem leży
>> w koncepcji...
>
> Nie zawsze można to zrobić, nie zawsze warto to robić, czasami dobrze
> jest zostawić wolną rękę implementacjom - w końcu kto powiedział, że
> jak implementujemy interfejs to nie możemy dodać coś od siebie i to
> udokumentować. Nie zawsze jest tak, że różne implementacje tego samego
> interfejsu są wzajemnie wymienne w naszym kodzie - i to dobrze. Weźmy
> taki przykład: interfejs Map - możemy mieć obiekt HashMap, ale możemy
> mieć też implementację zwracaną przez #Collections.synchronizedMap -
> każdy z nich możemy przedstawić jako Map, ale działają inaczej, a
> interfejs Map nic na ten temat nie mówi. Z drugiej strony mamy
> interfejs np. BlockingQueue, który jasno wspomina jak to wszystko
> powinno działać biorąc pod uwagę wątki.
I tu się nie zgodzę. Map ma dobrze zdefiniowany interfejs. Wiadomo co on
robi. I różne implementacje.
Dodawanie 'czegoś od siebie' (do głównego zbiornika) nie jest za dobre.
Pewnie z powodu mieszania odpowiedzialności - to co chcesz dodać można
by wydzielić jako osobny interfejs. Więc po co mieszać i wprowadzać
konieczność rzutowania?
BlockingQueue jest implementacją interfejsu Queue. Interfejs Queue nie
wie nic o tym, że MOŻE (albo ze JEST) implementacja będąca bezpiczena
wątkowo. Dodatkowo, zobacz jaką sprytną implementacją. Bez zmiany metod
interfejsu Queue dodaje współbieżność... Dokładnie tak jak ja tutaj
próbuję wytłumaczyć, że wątki to dodatek, który zamiast eksponować
powinno się ukrywać.
I dlatego moje pytanie - jak wydzielić CO od JAK. Jeśli się da - super.
Jeśli się nie da - pomysł nie jest 'obiektowy' (w bardzo, bardzo
rygorystycznym tego słowa znaczeniu)...
Pozdrawiam.
keef
Technical Details
Message-ID:
<hoigb3$lrn$1@news.task.gda.pl>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.gazeta.pl!newsfeed.pionier.net.pl!news.nask.pl!news.nask.org.pl!news.task.gda.pl!not-for-mailReferences:
<4c3b4f20-3f62-4e54-9e3c-298e4ea6c3e5@g10g2000yqh.googlegroups.com> <ho5jpd$gir$1@news.onet.pl> <hog3hh$s2g$1@news.task.gda.pl> <343ca24e-feae-4bf0-ba6c-ea59a4884c35@x12g2000yqx.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.nask.pl!news.nask.org.pl!news.task.gda.pl!not-for-mail From: keef <a@a.com> Newsgroups: pl.comp.lang.java Subject: Re: czy wątki mogą świadczyć usługi? Date: Fri, 26 Mar 2010 15:28:51 +0100 Organization: CI TASK http://www.task.gda.pl/ Lines: 126 Message-ID: <hoigb3$lrn$1@news.task.gda.pl> References: <4c3b4f20-3f62-4e54-9e3c-298e4ea6c3e5@g10g2000yqh.googlegroups.com> <ho5jpd$gir$1@news.onet.pl> <hog3hh$s2g$1@news.task.gda.pl> <343ca24e-feae-4bf0-ba6c-ea59a4884c35@x12g2000yqx.googlegroups.com> NNTP-Posting-Host: 90-156-6-120.as.kn.pl Mime-Version: 1.0 X-Trace: news.task.gda.pl 1269613733 22391 90.156.6.120 (26 Mar 2010 14:28:53 GMT) X-Complaints-To: abuse@news.task.gda.pl NNTP-Posting-Date: Fri, 26 Mar 2010 14:28:53 +0000 (UTC) User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.1.8) Gecko/20100227 Thunderbird/3.0.3 In-Reply-To: <343ca24e-feae-4bf0-ba6c-ea59a4884c35@x12g2000yqx.googlegroups.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit