Du bist nicht angemeldet.

Lieber Besucher, herzlich willkommen bei: DeveloperTalk. Falls dies dein erster Besuch auf dieser Seite ist, lies bitte die Hilfe durch. Dort wird dir die Bedienung dieser Seite näher erläutert. Darüber hinaus solltest du dich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutze das Registrierungsformular, um dich zu registrieren oder informiere dich ausführlich über den Registrierungsvorgang. Falls du dich bereits zu einem früheren Zeitpunkt registriert hast, kannst du dich hier anmelden.

liro

Fortgeschrittener

  • »liro« ist der Autor dieses Themas

Beiträge: 180

Danksagungen: 36

  • Private Nachricht senden

1

14.01.2014, 11:13

ThreadLocal

Ein ThreadLocal ist eine Variable, die es einem ermöglicht, Objekte für eine spätere Verwendung im Kontext eines Threads anzulegen. Es ist sinnvoll, diese für immer wieder zu verwendende Objekte anzulegen. Darunter fallen unter Anderem Buffer.
Vorteile gegenüber der Parameterübergabe:
  • Der Thread muss das Objekt nicht selbst verwalten
  • Aufrufer muss nichts über die Variable wissen, noch nicht mal dass es sie gibt
  • Für eine neue Variable muss nicht jede Methode angefasst werden
  • Alle Methoden innerhalb der Aufrufkette brauchen die Variable nicht übergeben/-bekommen, selbst wenn sie diese selbst nicht benötigen
  • Sauberere APIs

Vorteile gegenüber globalen Pools:
  • Schneller, da nicht auf ein globales Objekt gelockt werden muss, dadurch kein Flaschenhals/Overhead
  • Dadurch auch weniger Risiko auf Fehler

So muss der Aufrufen sich nicht unnötig um die Variable kümmern und die Methodendefinition(API) wird einfacher.

ThreadLocal anlegen
Zu erst muss eine Instanz der Klasse ThreadLocal erzeugt werden, diese definiert man am besten als static final. Dadurch weiß Java schon mal, welche threadlokalen Variablen es überhaupt gibt. Um jedoch für jeden Thread eine eigene Instanz dieser Variablen zu erzeugen muss eine Art factory Methode verwendet werden. DIe API bietet hierfür die initialValue-Methode, diese überschreibt man.

Java-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package net.b128.tl;

import java.nio.ByteBuffer;

public class BufferUtils
{
  private static final ThreadLocal<ByteBuffer> localBuffer = new ThreadLocal<ByteBuffer>()
    {
      @Override
      protected ByteBuffer initialValue()
      {
        return ByteBuffer.allocate(32768);
      }
    };

  public static ByteBuffer getBuffer()
  {
    return localBuffer.get();
  }
}



ThreadLocal auslesen
Nun bietet die API auch eine get-Methode, diese holt sich zu erst eine Map. Diese Map wird für jeden Thread einzeln gespeichert. Sprich: der Zugriff ist rasend schnell, da nicht auf ein globales Object synchronisiert werden muss. In dieser Map sind dann alle TheadLocal-Instanzen für den aktuellen Thread verzeichnet. Danach wird nur noch die richtige Instanz herausgesucht und zurückgegeben. Wurde noch keine Instanz angelegt, wird diese über die initialValue-Methode angelegt.

Java-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package net.b128.tl;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ScatteringByteChannel;

public class NIOWorker
{
  // read wird immer aufgerufen, wenn neue Daten über z.B. ein Netzwerkinterface eingegangen sind.
  // Wird von einem ThreadPoolWorker aufgerufen, der nichts von Buffern weiß.
  public void read(ScatteringByteChannel src) throws IOException
  {
    ByteBuffer buffer = BufferUtils.getBuffer();
    buffer.clear();

    src.read(buffer);
    buffer.flip();

    //Daten in buffer verarbeiten
  }
}


Hinweis: Diese Dokumentation scheint falsch zu sein. Es muss uniqueNum statt uniqueId in der Methode getCurrentThreadId heißen. (Das hatte mich erst sehr verwirrt, deshalb sag ich das lieber im Voraus)

Dieser Beitrag wurde bereits 11 mal editiert, zuletzt von »liro« (14.01.2014, 21:08)


Es hat sich bereits 1 registrierter Benutzer bedankt.

Benutzer, die sich für diesen Beitrag bedankt haben:

Johannes S. (13.02.2015)

Erik

Profi

Beiträge: 1 274

Registrierungsdatum: 22.06.2011

Wohnort: Deutschland ;)

Danksagungen: 307

  • Private Nachricht senden

2

14.01.2014, 19:40

was genau bringt einem das jetzt?

Zitat

Bei ThreadLocals handelt es sich um eine Variable, die im Kontext eines Threads existiert. Diese ermöglicht es einem zum Beispiel Buffer anzulegen, die dann jeweils nur innerhalb des jeweiligen Threads verwendet werden.


Das kann ich auch mit ner normalen Variable O.o
Beste Webite im Internet ( ͡° ͜ʖ ͡°)
xinra.de

liro

Fortgeschrittener

  • »liro« ist der Autor dieses Themas

Beiträge: 180

Danksagungen: 36

  • Private Nachricht senden

3

14.01.2014, 20:34

Hab das oben mal ergänzt.


Hier ein (Pseudocode) Gegenbeispiel mit Methoden-Parametern(Im realen Code ist das Problem natürlich um einiges umfangreicher, weil die Aufrufkette länger ist. Das Problem sollte trotzdem deutlich sein.):

Java-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// ganz viele imports

class PoolWorker extends Thread
{
  public void run()
  {
    ByteBuffer byteBuffer = ByteBuffer.alloc(1337);
    CharBuffer charBuffer = CharBuffer.alloc(42);
    
    while( true )
      queue.getNextTask().run(byteBuffer, charBuffer);
  }
}

class Task
{
  private Channel channel;

  public void run(ByteBuffer byteBuffer, CharBuffer charBuffer)
  {
    readData(channel, byteBuffer, charBuffer);
  }

  private void readData(Channel channel, ByteBuffer byteBuffer, CharBuffer charBuffer)
  {
    channel.read(byteBuffer);
    
    //byteBuffer verarbeiten
    //charBuffer temporärer fürs Decoding von Strings verwenden
  }
}

Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von »liro« (16.01.2014, 10:02)


Erik

Profi

Beiträge: 1 274

Registrierungsdatum: 22.06.2011

Wohnort: Deutschland ;)

Danksagungen: 307

  • Private Nachricht senden

4

17.01.2014, 19:24

Das mit dem Channel macht keinen Sinn :D Das ist eine Instanzvariable, die einer privaten Funktion als Parameter übergeben wird?

Wie auch immer, ist ja net so wichtig :D Also sind das einfach nur superglobale (auf einen Thread begrenzte) variablen?
Beste Webite im Internet ( ͡° ͜ʖ ͡°)
xinra.de

liro

Fortgeschrittener

  • »liro« ist der Autor dieses Themas

Beiträge: 180

Danksagungen: 36

  • Private Nachricht senden

5

17.01.2014, 19:37

Das mit dem Channel macht keinen Sinn :D Das ist eine Instanzvariable, die einer privaten Funktion als Parameter übergeben wird?

Jop, der Code ist auch nicht vollständig, sollte nur das "Problem" aufzeigen.


Wie auch immer, ist ja net so wichtig :D Also sind das einfach nur superglobale (auf einen Thread begrenzte) variablen?

Jop, so könnte man's nennen :)

Verwendete Tags

multithreading, threading