🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.lang.java
Article #149856

Re: czy wątki mogą świadczyć usługi?

#149856
From: keef
Date: Fri, 26 Mar 2010 14:28
125 lines
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-mail
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>

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