Grafiska användargränssnitt (GUI) GUI byggs av widgets (grafiska) som t ex fönster, knappar, in- och utmatningsfält, ritytor, I Java kallas sådana delar komponenter. I Java används klasser ur awt (abstract window toolkit) som är en betydande del av Javas API Grafiska användargränssnitt, forts Det finns flera olika typer av grafiska komponenter i Java: Button, Checkbox, List, Choice, Lable, TextField, TextArea, Scrollbar En kontainer är en komponent som kan innehålla andra komponenter. En komponent läggs in i en kontainer med metoden add(component) public class Demonstrate { public static void main (String args []) { Frame f = new Frame("Test-Window"); f.setsize(300, 100); f. setvisible(true); Argumentet till Frames konstruktor är fönstrets rubrik, setsize(300, 100) sätter storleken på fönstret och setvisible(true) gör att fönstret blir synligt. Instanser av Panel brukar användas för att organisera de grafiska komponenterna. Kjell Lindqvist Sid 217 Kjell Lindqvist Sid 218 awt Fönstret får automatiskt en knapp för att avsluta, en knapp för att "ikonifiera" och en knapp för att expandera fönstret. Programmet terminerar inte eftersom det väntar på musrörelser, musknapptryckningar och tangenttryckningar (på tangentbordet). testwindow måste tillhandahålla en "fönsterlyssnare". public class testwindow2 extends Frame{ public testwindow2 (String title) { super(title); addwindowlistener(new WindowAdapter() { public void windowclosing(windowevent e) { System.exit(0); ); setsize(300, 100); setvisible(true) (); public static void main(string[] args) { new testwindow2("testwindow"); Object Component Color Font JTextComponent JTextField JTextArea Klasshierarki Container Panel JComponent JPanel AbstractButton JToggleButton JButton JMenuItem JCheckBox JRadioButton JRadioButtonMenuItem JCheckBoxMenuItem JMenu Applet JApplet JComboBox JLabel JList JMenuBar JPane JPopupMenu JScrollbar JScrollPane JTable JTree Kjell Lindqvist Sid 219 Kjell Lindqvist Sid 220
Swing Viktiga paket för fönsterhantering AWT - Abstract Windowing Toolkit (java.awt) Swing (javax.swing) Händelser, lyssnare (java.awt.event) AWT är det ursprungliga fönsterpaketet, Swing är det nyare. OBS att AWT dock innehåller en hel del som även används i Swing, t.ex klasserna Graphics och Color. AWT abstrakt i den meningen att det är "oberoende" av operativsystem AWT använder i grunden så kallade "native widgets", operativsystemets egna komponenter AWT innehåller dels komponenter (widgets) dels klasser för bilder och andra GUI-objekt. Swing Swing är än mer oberoende av operativsystem än AWT Swing använder så kallade "lättviktskomponenter" programmerade i Java Swing-komponenterna ersätter motsvarade klasser i AWT (dessa prefixas med J, som JButton) Swing har omfattande stöd för olika GUI-delar, t.ex visning av HTML Swing har rykte om sin att vara långsamt och komplext - det är inte längre sant, nya versioner är snabbare Kjell Lindqvist Sid 221 Inmatningstyper Request mode Vänta tills dess att något sker tex på inmatning via tangentbordet eller klick på mus traditionell inmatning från tangentbord, scanf (C), readln (Pascal) sensor.waitbutton(); gc.displaystring("inmatning ", sensor.pos()); Där sensor är ett (tänkt) objekt som ger oss möjlighet att läsa av inmatningsverktygens status (dvs tex tangentbord och mus) Samplad/pollad Kontrollera status för enhet Omedelbar avläsning tex är någon knapp på musen nertryckt while(sensor.anybuttonpressed()) { pen.moveto(sensor.mousepoint()); Händelsestyrd Förändringar hos enheter placeras i en kö intresserade program meddelas om att händelse inträffat från början av kön (flera kan alltså meddelas om samma händelse) Kjell Lindqvist Sid 222 Inmatningstyper, forts Det är sedan upp till varje program att själv bestämma hur det skall (eller inte skall) reagera Exempel, en metod som reagerar om händelsen dubbeklick inträffar public void doubleclickevent(event event) { frame.setlocation(event.position()); Eventmodell 1.1 Förutom de vanliga styrstrukturerna sekvens, selektion, iteration och rekursion, används i Java ofta händelsebaserade kontrollstrukturer. Händelsebaserad programmering ("event-oriented programming") blev populärt i och med GUIs där "callbacks" var vanliga. En callback är en procedur som anropas av kod som ligger "utanför" mitt eget program. Callbacks/händelser är ett naturligt sätt att programmera grafiska användargränssnitt eftersom interaktionen består av olika händelser som användaren genererar. Inmatning i Java bygger på händelser. När något händer i användargränssnittet skickas ett meddelande om detta till en lyssnare. En lyssnare är ett objekt som är kopplat till en komponent och får meddelanden ("events") från denna. Det finns flera olika typer lyssnare, en för varje kategori av händelser. Lyssnarna är oftast interface vars metoder man implementerar i sin egen lyssnare. Kjell Lindqvist Sid 223 Programmet byggs upp på ett sådant sätt att det är "berett" att reagera på olika händelser/interaktioner. Ofta används begreppet "ramverk" om klassbibliotek där man "pluggar in" egna klasser vars metoder anropas från ramverksklasserna. Java 1.1 och senare har en modell där man definierar objekt som tar hand om händelser som sker i komponenter i gränssnitten. Kjell Lindqvist Sid 224
Händelselyssnare Lyssnare Händelser till ett fönster eller komponent tas omhand av händelselyssnare Beroende av typ av lyssnare måste olika API:er implementeras. Olika typer av lyssnare tar hand om olika typer av händelser, MouseListener, WindowListener, FocusListener, ActionListener, osv. Namnet är uppbyggt på följande sätt: HändelsetypListener Till varje lyssnare finns ett speciellt interface som beskriver vilka metoder som lyssnaren implementerar Lyssnarna och deras interface tillhör ett gemensamt package nämligen: java.awt.event Lyssnarna är oftast interface vars metoder man implementerar i sin egen lyssnare. Två olika tekniker: Använd en lyssnarklass för flera komponenter Använd en egen lyssnarklass för varje komponent Man kan med fördel använda en inre klass för varje lyssnare. Kjell Lindqvist Sid 225 Kjell Lindqvist Sid 226 Exempel import java.awt.event.*; public class MyFrame1 extends Frame implements WindowListener{ public void windowopened(windowevent e) { public void windowclosing(windowevent e) { System.exit(0); public void windowclosed(windowevent e) { public void windowiconified(windowevent e) { public void windowdeiconified(windowevent e) { public void windowactivated(windowevent e) { public void windowdeactivated(windowevent e) {... public static void main(string [] args) { MyFrame1 frame = new MyFrame1(); frame.settitle("fönster som lyssnar efter fönsterhändelser"); frame.setsize(400, 300); frame.addwindowlistener(frame); frame.setvisible(true); Kjell Lindqvist Sid 227 Adaptorer och händelselyssnare För att förenkla användningen av händelselyssnare finns ett antal fördefinierade adaptorer. Dessa adaptorer implementerar alla metoder deklarerade i den aktuella lyssnarens gränssnitt. En adaptor implemeneterar endast tomma metoder. Genom att subklassa en adaptor och använda den som lyssnare så räcker det att endast skriva om dom metoder som verkligen gör något, så slipper man implementera massa metoder utan metodkropp. Dessa adaptorer är speciellt enkla att använda tillsammans med anonyma inre klasser. Applets En applet är en applikation som hanteras av en web browser. Metoder som anropas automatiskt: 1. public void init() anropas en gång då en applet skapas 2. public void start() varje gång man återvänder till HTML sidan 3. public void paint(graphics g) varje gång som en applet behöver ritas om 4. public void stop() då man lämnar HTML sidan 5. public void destroy() då en applet "dör" Kjell Lindqvist Sid 228
ComponentAdapter ContainerAdapter FocusAdapter Adaptorer ActionListener AdjustmentListener Componentlistener ContainerListener Subklasser: BorderLayout Layoutmanager är default i Frame och Dialog. Placerar komponenter i vädersträck KeyAdapter FocusListener ItemListener 1 - NORTH 2 - CENTER 3 - SOUTH MouseAdapter MouseMotionAdapter WindowAdapter KeyListener MouseListener MouseMotionListener WindowListener TextListener 1 - WEST 2 - CENTER 3 - EAST 4 - NORTH 5 - SOUTH 1 - WEST 2 - CENTER 3 - EAST Kjell Lindqvist Sid 229 Kjell Lindqvist Sid 230 Layoutmanager, forts GridLayout ser till att alla komponenter är lika stora. Matris för komponenter. Artgumenten är: Antal rader Antal kolumner Horisontellt avstånd mellan ruterna Vartikalt avstånd mellan ruterna. FlowLayout Är default för Panel. Layoutmanager, forts Placerar komponenter från vänster till höger, ny rad då det behövs. Följer med då fönstrets storlek ändras. import java.applet.*; public class DemoGridLayout extends Applet { public void init() { super.init(); setlayout(new GridLayout(5, 2, 5, 5)); Kjell Lindqvist Sid 231 Kjell Lindqvist Sid 232
Layoutmanager, forts GridBagLayout Mest generell. Delar ytan i flera celler. Restriktioner bestämmer hur komponenterna skall placeras och deras utsträckning. GridBagLayout får sina restriktioner från GridBagConstraints GridBagLayout gbl = new GridBagLayout(); setlayout(gbl); GridBagConstraints gbc = new GridBagConstraints(); gbc.weightx = 1.0; // sprid ut horisontellt gbc.weighty = 1.0; // sprid ut vertikalt gbc.fill = GridBagConstraints.BOTH; // sprid ut horisontellt gbc.gridx = 1; //övre vänstra hörnet i panelen är på rad 2 gbc.gridy= 2; // och 3:e kolumnen gbc.gridwidth = 2; // panelen sprids över 2 kolumner gbc.gridheight = 1 // och en rad gbl.setconstraints(apanel, gbc); add(apanel); Exempel knappraden 0 1 2 tabellen til vänster listan till höger 0 1 2 3 ledtexten nederst gridx 0 0 3 1 2 gridy 0 1 1 2 2 gridwidth 4 3 1 1 1 gridheight 1 1 1 1 1 textboxen fill NONE BOTH BOTH NONE HORIZONTAL anchor WEST CENTER CENTER EAST WEST Kjell Lindqvist Sid 233 Kjell Lindqvist Sid 234 Ramverk Ett framework beskriver hur ett problem skall brytas ner. Vanlig situation: Användarkod kod i klassbibliotek Med användning av framework blir situationen omvänd: FrameWork Användarkod Hollywood-principen: ring inte oss, vi ringer er! Kjell Lindqvist Sid 235 Menyer MenuBar menubar = new MenuBar(); Menu filemenu = new Menu("File"); MenuItem fileopen = new MenuItem("Open"); MenuItem fileclose = new MenuItem("Close"); setmenubar(menubar); menubar.add(filemenu); filemenu.add(fileopen); filemenu.add(fileclose); // Deal with menu items: public boolean action (Event e, Object o) { if (e.target == fileopen) { FileDialog dialog = new FileDialog(this, "Load Movies"); dialog.setfile("*.movies"); dialog.show(); String file = dialog.getfile(); System.out.println(file); if (file!= null) { setmovievector(file); dialog.dispose(); return true; Kjell Lindqvist Sid 236
Menyer, forts else if (e.target == filemenuexit) { System.exit(0); return true; else {return false; // Deal with close button: public boolean handleevent(event e) { switch (e.id) { case Event.WINDOW_DESTROY: System.exit(0); return true; default: return super.handleevent(e); meny (JMenu) menypost (JMenuIte menylinje (JMenuBar) Menyer knapp (JButton) (JToolBar) Knappraden på vanlig plats Fildialog: FileDialog dialogvariabel = new FileDialog(this, titelsträng) Restriktioner: dialogvariabel.setfile(filename, pattern); extrahera filen som resultat av en fildialog: file-dialogvariabel.getfile(); Knappraden har dragits Till en egen plats Kjell Lindqvist Sid 237 Kjell Lindqvist Sid 238 Trådar Då vi startar ett program så startar vi också en process. Flera processer kan exekvera samtidigt (äkta parallellitet eller kvasiparallellt) (multitasking). Även ett program kan initiera flera processer (uppdelning av komplicerade beräkningar, utskrift i bakgrunden, ). Sådana lokala processer kallas trådar. Vid kvasiparallell exekvering fördelar systemet tiden mellan trådarna. Byte av tråd kallas kontextbyte. Vi kan ha flera processer där var och en har ett antal trådar. Man kan tänka sig två metoder att fördela tiden mellan trådarna: Tråden själv tar en paus i exekveringen. Operativsystemet fördelar tiden mellan trådarna. Mekanismen i java är beroende av interpretatorn. Trådar, forts Normalt har ett program endast en exekveringstråd, den som startar i mainmetoden och sedan via metodanrop flyttar exekveringen till andra metoder i programmet. Med endast en tråd är det möjligt att i varje ögonblick säga att programmet exekverar en specifik programsats. Med flera trådar är det möjligt att exekvering pågår på flera ställen i programmet samtidigt. Då vi inte har möjlighet till "äkta" parallellitet så sker exekveringen "kvasiparallellt" d v s vi simulerar parallelliteten. Trådar kan användas i en mängd olika syften: programmet har flera olika parallella aktiviteter att hantera Ex: En tråd sköter kommunikation med användaren, en annan tråd sköter kommunikation med en server. programmet innehåller flera olika objekt som skall kunna agera självständigt Ex: En animeringssekvens där varje figur hanteras av en tråd. programmet hanterar vissa uppgifter i bakgrunden. Ex: Rapporter skrivs ut medan användaren fortsätter att arbeta. Kjell Lindqvist Sid 239 Kjell Lindqvist Sid 240
Problem med trådar Resurser kan tas i anspråk av flera trådar och operationerna kan då komma i konflikt med varandra. Vi kan råka ut för deadlock och utsvältning. En tråds livscykel Trådar måste kunna synkroniseras (invänta resultat från andra trådar). tråd 1 Initiering tråd 2 Fork-linje Del ett av beräkningen Del två av beräkningen Synkronisering Beräkning som kräver båda resultaten Kjell Lindqvist Sid 241 Kjell Lindqvist Sid 242 static void sleep(long millis) Metoder söver ner den tråd som exekverar static void sleep(long millis, int nanos) söver ner den tråd som exekverar void start() void final interrupt() static yield() startar exekveringen av tråden stoppar exekveringen av tråden stoppar tillfälligt den tråd som nu exekverar Det kan se konstigt ut med statiska metoder men om de anropas i en tråds metod arbetar de ju på den tråden eftersom det är den som exekverar. Ingen av metoderna ovan ersätts vanligen, man anropar dem vid behov. Animering Exempel med trådar är en enkel animering. Appleten nedan visar en text som skyms av en oval som ändrar storlek. Exempel import java.applet.*; public class WelcomeAnimation extends Applet implements Runnable { static final int sleepingtime = 100; static final String msg = "Welcome to the World of Internet Programming"; private Font font; private int size = 100; private boolean shrinking = true; private Thread animator = null; public void init() { super.init(); font = new Font("Times", Font.BOLD, 12 ); setbackground( Color.white ); public void start() { // Appletens start(), *ej* trådens animator = new Thread( this ); // Skapa en tråd animator.start(); public void stop() { animator = null; Kjell Lindqvist Sid 243 Kjell Lindqvist Sid 244
; Exempel, forts public void paint( Graphics g) { g.setcolor(color.red); g.filloval(230-size*3/2, 97-size/2, size*3, size); if (shrinking) { size = size - 2; if (size == 0) shrinking = false; else { size = size + 2; if (size == 100) shrinking = true; g.drawstring( msg, 100, 100); public void run() { while (true) { repaint(); try { Thread.sleep(sleepingTime); catch (InterruptedException e) { System.exit(1); public void destroy() { if ( animator!= null ) { animator = null; // För att hjälpa skräphanteraren... Kjell Lindqvist Sid 245 Skapa en tråd I Java har vi två möjligheter att skapa trådar: skriva en subklass till Thread implementera gränssnittet Runnable Om man skapar en subklass till Thread så definieras (normalt) metoden run om: class mythred extends Thread { public void run() { Eller då vi implementerar Runnable: class mythred implements Runnable { public void run() { Tänk på att då run terminerar så dör tråden. run innehåller oftast en oändlig loop! Då vi implementerar Runnable så måste alla metoder från Runnable implementeras! Kjell Lindqvist Sid 246 Dubbelbuffring Appleten i föregående avsnitt kanske (det beror på nätbläddrare, dator, andra appliktioner, etc ) flimrar på ett obehagligt sätt. Det finns flera tekniker att minska flimret och en vanlig teknik är s.k. dubbelbuffring, d.v.s man ritar sin bild i ett "fönster" i minnet och överför sedan hela bilden till skärmen. I Java är det lätt att ordna detta genom att ersätta metoden update(): import java.applet.*; public class WelcomeAnimationSmooth extends Applet implements Runnable { static final int sleepingtime = 100; static final String msg = "Welcome to OOP1"; private Font font; private int size = 100; private boolean shrinking = true; private Thread animator = null; Graphics offscreengraphics; /* New in double buffered version */ Image offscreenimage; /* New in double buffered version */ Dimension offscreendim; /* New in double buffered version */ Kjell Lindqvist Sid 247 Dubbelbuffring, forts public void init() { super.init(); font = new Font("Times", Font.BOLD, 12 ); setbackground( Color.white ); public void start() { animator = new Thread( this ); animator.start(); public void stop() { animator = null; public void paint( Graphics g) { update(g); public void update( Graphics g) { /* New in double buffered version */ Dimension d = getsize(); if (offscreengraphics == null ) { offscreendim = d; offscreenimage = createimage( d.width, d.height); offscreengraphics = offscreenimage.getgraphics(); Kjell Lindqvist Sid 248
Dubbelbuffring, forts offscreengraphics.setcolor( getbackground() ); offscreengraphics.fillrect(0,0,d.width,d.height); offscreengraphics.setcolor( Color.red ); offscreengraphics.filloval(230-size*3/2, 97-size/2, size*3, size); if (shrinking) { size -= 2; if (size == 0) shrinking = false; else { size += 2; if (size == 100) shrinking = true; offscreengraphics.drawstring( msg, 100, 100); g.drawimage( offscreenimage, 0,0, this); public void run() { while (true) { repaint(); try { Thread.sleep(sleepingTime); catch (InterruptedException e) { System.exit(1); Kjell Lindqvist Sid 249 Olika trådar arbetar ibland på samma data. Synkronisering För att detta skall fungera krävs att trådarna synkroniseras så att inte en av trådarna läser data som inte finns, data som redan lästs av andra osv. Betrakta följande exempel: public class threadexample { private int counter = 0; public int nextcounter() { return counter++; Antag att två trådar t1 och t2 använder en instans av klassen: t1 läser värdet och finner att det är 0 t2 läser värdet och finner att det är 0 t1 adderar 1 till det tidigare värdet och skriver det nya värdet (1) till counter t2 adderar 1 till det tidigare värdet och skriver det nya värdet (1) till counter Den ena trådens uppdatering har gått förlorat! Kjell Lindqvist Sid 250 Låsning För att undvika konflikt av denna typ kan man låsa objektet under den tid det tar för trådens uppdatering. I Java har varje objekt ett associetat lås. En metod som använder en synchronized modifierare, får automatiskt ett lås på sin instans innan man kan fortsätta. Om instansen redan är låst blockeras metodanropet tills låset är släppt och man kan erhålla sitt lås. I vårt exempel ser det ut på följande sätt: public class threadexample { private int counter = 0; public synchronized int nextcounter() { return counter++; t1 vill läsa värdet och får ett lås, t1 finner att värdet är 0 t2 vill läsa värdet och får vänta t1 adderar 1 till det tidigare värdet och skriver det nya värdet (1) till counter samt släpper låset t2 får sitt lås, läser värdet (1) adderar 1 till det tidigare värdet och skriver det nya värdet (2) till counter samt släpper låset. Kjell Lindqvist Sid 251 Låsning, forts Det är möjligt för en metod att få ett lås på ett annat objekt än sitt eget. Man använder i detta fall ett synchronized block: public class synchronizedblockexample { private int counter = 0; public int getcounter() { return counter; public void setcounter(int i) { counter = i; synchronizedblockexample mycounter = new synchronizedblockexample(); synchronized (mycounter) { int currentcounter = mycounter.getcounter(); mycounter.setcounter(currentcounter++); Inget annat block kan komma åt mycounter under blockets exekvering. Kan detta skapa nya problem? Kjell Lindqvist Sid 252
Deadlock Om t1 har låst objektet obj1 och behöver objektet obj2 för sin fortsatta exekvering och t2 har låst objektet obj2 och behöver objektet obj1 för sin fortsatta exekvering uppstår s k deadlock. Detta måste programmeraren själv hantera. Exempel: På kursbiblioteket finns en applet visar en producent-konsument situation med ett lager med plats för 20 varor av något slag. Programmet har tre klasser: SynchronizerDemo, Producer och Consumer varav de båda senare exekverar i varsin tråd och alltså asynkront placerar varor i lagret respektive tar bort dem. För att göra det hela litet mer intressant finns en slumpmässig försening i klasserna. Dessutom kan man suspendera och starta om både producent och konsument. När lagret är fullt och producenten vill lägga in en vara (men alltå måste vänta) visas en röd markering på "producentsidan" och om lagret är tomt och konsumenten försöker hämta en vara visas motsvarande markering på "konsumentsidan". Lagret visas som en stapel i mitten. Kjell Lindqvist Sid 253 Synkronisering, forts Man använder kvalificeraren synchronized för att synkronisera metoder: alla metoder som inte får exekvera samtidigt deklareras synchronized. Under tiden som en synkroniserad metod exekverar kan alltså ingen annan synkroniserad metod startas. De andra verktygen för synkronisering är metoderna wait() och notify(). Man anropar wait() i en synkroniserad metod för att låta en annan tråd exekvera så att skälet till att man väntar kan upphävas. notify() är motsatsen till wait(): man väcker upp en väntande tråd efter att något skett med objektet, i vårt fall att lagret inte längre är tomt respektive att det inte längre är fullt. Det objekt som väcks är det som har egenrätt på SynchronizerDemo-instansen just nu, d.v.s. det objekt som startade en synkroniserad metod. Observera att metoden wait() alltså släpper "låset" på objektet SynchronizerDemo så att producenten eller konsumenten kan uppdatera objektet. Kjell Lindqvist Sid 254 Synkronisering, forts Konsumenten och producenten är båda arvtagare till Thread och har alltså redan ärvt gränssnittet Runnable genom Thread. Det kanske mest intressanta med klasserna är att ingendera innehåller några konstigheter: All synkronisering sker i klassen SynchronizerDemo. Allt Producer och Consumer gör är att producera och konsumera så fort de kan. Multithreading Multithreading är att flera trådar kan exekvera samtidigt i ett program. Vi har redan i exemplet SynchronizerDemo sett att två trådar kan exekvera samtidigt och till och med synkroniserat dem. Med multithreading avses oftast att flera trådar arbetar asynkront: t.ex. att en tråd utför något tungt i bakgrunden medan en annan tråd håller igång användargränssnittet. Kjell Lindqvist Sid 255 Schedulering av trådar Schemaläggningen av trådar är inte i detalj definierad i Java. Detta betyder att egenskaper i OS har inverkan på exekveringen. Följande gäller dock: trådar med högre prioritet exekverar före trådar med lägre prioritet. trådar med lika prioritet får omväxlande exekvera. trådar med lägre prioritet får endast exekvera då trådar med högre prioritet är blockerade. En tråds prioritet kan normalt vara någon av Thread.MIN_PRIORITY, Thread.NORMAL_PRIORITY och Thread.MAX_PRIORITY. En tråds prioritet avläses med getpriority() och sätts med setpriority(prioritet). Eftersom trådarnas prioritetskonstanter är definierade som: public final static int MIN_PRIORITY = 1; public final static int NORMAL_PRIORITY = 5; public final static int MAX_PRIORITY = 10; så är det tillåtet att sätta prioriteten till ett värde i [1..10]. Kjell Lindqvist Sid 256
Schedulering av trådar Metoden static native Thread currentthread() ger en referens till den exekverande tråden. Metoden final native boolean isalive() ger true om tråden startats och inte terminerat. Då vi använder trådar med olika prioritet kan en tråd med låg prioritet få vänta i oändlihet om vi succesivt startar trådar med högre prioritet detta kallas utsvältning. Varje tråd i java är medlem i en trådgrupp. Grupper av trådar En trådgrupp är en mekanism för att hantera gruppen som helhet i stället för att hantera individuella trådar. T ex kan man starta eller suspendera alla trådar i en grupp. En trådgrupp i Java implementeras med ThreadGroup class i java.lang package. Runtimesystemet placerar en tråd i en trådgrupp då den skapas. Man kan då välja att låta runtimesystemet placera tråden i en "default" grupp eller explicit placera den i en grupp. Då den placerats i en grupp kan den inte flyttas. Grupper av trådar Om man inte specifierar gruppen så blir den samma som den som den skapande tråden tillhör. Nya trådar placeras i en trådgrupp med konstruktorerna: public Thread(ThreadGroup group, Runnable target) public Thread(ThreadGroup group, String name) public Thread(ThreadGroup group, Runnable target, String name) En trådgrupp och en tråd kan konstrueras enligt följande: ThreadGroup mythreadgroup = new ThreadGroup("My Group of Threads"); Thread mythread = new Thread(myThreadGroup, "a thread for my group"); Man kan få tag i trådgruppen med metoden: thegroup = mythread.getthreadgroup(); Kjell Lindqvist Sid 257 Kjell Lindqvist Sid 258