Klasa licząca długość lifetime wątku

0

Cześć.
Jestem dosyć pokorna wobec Javy wielowątkowej. Zwracam się do was z zapytaniem czy taka implementacja jak poniżej do mierzenia
lifetime'u (czasu ile dany wątek już żyje) jest okey?

Dodam, że metody będą używane przez kilka wątków jednocześnie.

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;

import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Slf4j
public final class ThreadLifeTimeCounter {

    private static final ConcurrentMap<Thread, StopWatch> THREAD_TO_STOPWATCH =
            new ConcurrentHashMap<>();

    public static void startFor(Thread thread) {
        THREAD_TO_STOPWATCH.put(thread, StopWatch.createStarted());
    }

    public static long getInMsAndFinish(Thread thread) {
        return Optional.ofNullable(THREAD_TO_STOPWATCH.remove(thread))
                .map(stopWatch -> {
                    stopWatch.stop();
                    return stopWatch.getTime();
                })
                .orElseThrow(() -> new IllegalArgumentException("Thread not started counting life time"));
    }
}
2

Jeżeli jeden wątek wywołuje startFor a inny getInMsAndFinish to formalnie nie bo:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/time/StopWatch.html
' ... This class is not thread-safe'

Update:
Po poście @rubaszny_karp widać, że to wyzej bzdura. Nie da się współdzielić niechcący współdzielić StopWatch. (Bo wyciąganie jest tylko przez remove() dwa razy z tej mapy tego samego StopWatch sie nie wyciągnie).

0

@jarekr000000: ale dlaczego kiedy ten StopWatch nie jest współdzielony? Jedynie ConcurrentHashMap jest współdzielona a instancje obiektu StopWatch każdy wątek ma swoją osobną w tejże mapie.

2

Dlatego tak napisałm założenie. Z tego kodu nie widać, że StopWatch nie jest" współdzielony". Każdy ma dostęp - mając tylko referencję do Thread :-).

0

A no dobra rzeczywiście masz racje teraz rozumiem. I takie sytuacje też u mnie wystąpią. Kurde słabo. Napisałam wersje 2.0

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;

import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Slf4j
public final class ThreadLifeTimeCounter {

    private static final ConcurrentMap<Thread, StopWatch> THREAD_TO_STOPWATCH =
            new ConcurrentHashMap<>();

    public static void startFor(Thread thread) {
        synchronized (thread) {
            THREAD_TO_STOPWATCH.put(thread, StopWatch.createStarted());
        }
    }

    public static long getInMs(Thread thread) {
        synchronized (thread) {
            return Optional.ofNullable(THREAD_TO_STOPWATCH.get(thread))
                    .orElseThrow(() -> new IllegalArgumentException("Thread not exists"))
        }
    }

    public static boolean remove(Thread thread) {
        synchronized (thread) {
            return THREAD_TO_STOPWATCH.remove(thread) != null;
        }
    }
}
0

dobra to chyba nie ma sensu inaczej musze to zrobić (po prostu w klasie ktora jest moim wątkiem tam zrobić ten stopwatch

2

Jeżeli stopWach nigdy nie ucieknie z obiektu klasy ThreadLifeTimeCounter (a, aktualnie nie ucieknie) to wszytko jest ok - liczy się tylko happens-before które zapewnia tutaj mapa.

Osobiście jednak wolałbym mieć, zamiast takiej klasy, wątek który jest świadom ile żyje.

P.S Ta wersja z synchrizacją nie ma sensu :D

P.S putIfAbsent chyba zamiast put ?

0

@rubaszny_karp: OOOOOOOOOOOOOOOOOOOOOO <3 Rubaszny Karp akka największy mózg tego forum akka Następca Shaloma akka AKKA.IO XD aka Zdecydowany na Jave i HFT.

Dzięki wielkie!!!

rubaszny_karp napisał(a):

Osobiście jednak wolałbym mieć, zamiast takiej klasy, wątek który jest świadom ile żyje.

Ja też ale mój wątek robi wiele rzeczy i jest skomplikowany itd i po prostu nie chce obarczać go kolejną odpowiedzialnością tj. zajmowaniem się liczeniem swojego life time'u.
Tak to nie potrzebuje żadnego pola prywatnego ani żadnych w nim metod tlyko w pewnym momencie wale ThreadLifeTimeCounter.startFor(this); i w pewnym momencie long liveTimeInMs = ThreadLifeTimeCounter.getInMsAndFinish(this); i tyle. @rubaszny_karp do BOJU !

PS na forum wprowadzono w postach kolorowanie czeskich błędów na czerwono to jest irytujące i lepiej żeby była autokoretka

1

największy mózg tego forum

nawet umiem proste granice policzyć.

Ja też ale mój wątek robi wiele rzeczy

ale to nie Twój wątek powinien to robić tylko thread poola (tak mi sie wydaje)
robisz tak, rozszerzasz ThredPoolExecutor (java.util.concurrent.ThreadPoolExecutor) i nadpisujesz takie dwie metody jak

protected void beforeExecute(Thread t, Runnable r) { }
protected void afterExecute(Runnable r, Throwable t) { }

i tutaj możesz korelować czas wykonania z Runnable, masz before i aftera, nic nie wycieka na zewnątrz, może to jest droga ?

Pytanie, czy musisz robić nowy thread za każdym razem ? dlaczego nie możesz używać jednego i robić tego non-blocking ?

0

Nie musze robić nowego wątku za każdym razem. I tak samo miałam jakąś trudność w wykonaniu tego samego bez rozszerzania Thread a tylko w korzystaniu z ThreadPoolExecutor i Runnable / Callable. Ale pomyślę nad tym i poczytam w kolejnych etapach rozwoju aplikacji.

beforeExecute / afterExecute dzięki.

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