Lõim pärib oma prioriteedi sellelt lõimelt, mis ta tekitas.
Klassis Thread on täisarvulised konstandid MIN_PRIORITY, NORM_PRIORITY ja MAX_PRIORITY (kasvamise järjekorras), mida saab kasutada lõime prioriteedi muutmiseks meetodiga setPriority(). Antud lõime prioriteedi tagastab meetod getPriority().
Pole mingit mõtet anda lõimedele maksimaalset prioriteeti - olukord sellest tavaliselt ei parane. Pigem on otstarbekas osade lõimede prioriteete vähendada.
Näit.:
int prio = Thread.NORM_PRIORITY -
tagaPlaan.start();
Sisenemisel "kriitilisse sektsiooni" objekt lukustatakse, teised lõimed saavad objekti kasutada alles siis, kui lukk on maha võetud, s.t. esialgne lõim on "kriitilisest sektsioonist" väljas.
Lukustamise ja lukkude eemaldamise mehhanismi tuntakse ka monitori nime all. Iga objektiga (ja ka iga klassiga) on seotud oma monitor, seepärast ongi wait(), notify() ja notifyAll() klassi Object isendimeetodid.
obj.wait() peatab jooksva lõime töö ning avab obj luku niikauaks, kuni mingi teine lõim saadab teate obj.notify(). Leidub ka üledefineeritud wait(ms) versioon, mille toimel lõim siiski "ärkab" etteantud aja möödudes.
Kuna sama objekti obj taga võib olla mitu ootajat, siis tuleks tegelikult kasutada obj.notifyAll(), mis "äratab" kõik obj järele ootajad (see, mis edasi juhtub, on prioriteetide ja ajajaotuse küsimus; kui võitja on selgunud, siis lähevad ülejäänud lõimed ooteseisundisse tagasi).
Kõiki neid meetodeid kasutatakse kriitilise sektsiooni sees.
public class Threads { public static void main (String[] args) { MyThread t1 = new MyThread("1"); MyThread t2 = new MyThread ("2"); t1.start(); t2.start(); } // main } // Threads class MyThread extends Thread { private String name; MyThread (String s) { name = s; } // constructor public void run() { for (int i=0; i<500; i++) { try { sleep(20); } catch (InterruptedException e) {} System.out.print (name); } // for } // run } // MyThread
import java.util.*;
/** Producer-Consumer demo.
* @author Jaanus Poial
* @version 0.3
* @since 1.5
*/
public class ConsProd5 {
/** buffer capacity */
public static final int BUFLEN = 6;
/** shared buffer */
public static ArrayList <String> buf = new ArrayList <String> (BUFLEN);
/** Main method */
public static void main (String[] param) {
int producer1_tick = 5000; //millisec
int producer2_tick = 7000; //millisec
int consumer1_tick = 3000; //millisec
Producer producer1 = new Producer (producer1_tick, "Pro1");
Producer producer2 = new Producer (producer2_tick, "Pro2");
Consumer consumer1 = new Consumer (consumer1_tick, "Con1");
System.out.println ("Buffer capacity: " + BUFLEN);
producer1.start();
producer2.start();
consumer1.start();
} // main
} // ConsProd5
/** Producer thread. */
class Producer extends Thread {
/** time to produce an item in milliseconds */
int tick;
/** producer label */
String name;
/** producer thread constructor */
Producer (int i, String s) {
tick = i;
name = s;
}
/** producer thread content */
public void run() {
try {
while (true) { // infinite loop
produce(); // produce an item after each tick
sleep (tick);
}
}
catch (InterruptedException e) {
}
} // run
/** producing process */
private void produce()
throws InterruptedException {
synchronized (ConsProd5.buf) {
while (ConsProd5.buf.size() >= ConsProd5.BUFLEN) {
ConsProd5.buf.wait(); // buffer is full, wait
}
ConsProd5.buf.add ("(" + name + " > " +
new Date().toString() + ")"); // timestamp
System.out.println (name + " > " +
ConsProd5.buf.get (ConsProd5.buf.size()-1) +
" " + tick + " " + ConsProd5.buf.size());
ConsProd5.buf.notifyAll();
} // end of critical section
} // produce
} // Producer
/** Consumer thread. */
class Consumer extends Thread {
/** time to consume an item in milliseconds */
int tick;
/** consumer label */
String name;
/** consumer thread constructor */
Consumer (int i, String s) {
tick = i;
name = s;
}
/** consumer thread content */
public void run() {
try {
while (true) { // infinite loop
consume(); // consume an item after each tick
sleep (tick);
}
}
catch (InterruptedException e) {
}
} // run
/** consume an item */
private void consume()
throws InterruptedException {
synchronized (ConsProd5.buf) {
while (ConsProd5.buf.size() <= 0) {
ConsProd5.buf.wait(); // buffer is empty, wait
}
String message = (String)ConsProd5.buf.get (0);
System.out.println (name + " < " +
message + " " + tick);
ConsProd5.buf.remove (0); // consume!!
ConsProd5.buf.notifyAll();
} // end of critical section
} // consume
} // Consumer
import java.util.*;
/** Producer-Consumer demo.
* @author Jaanus Poial
* @version 0.3
* @since 1.5
*/
public class RunnableCP5 {
/** buffer capacity */
public static final int BUFLEN = 6;
/** shared buffer */
public static ArrayList <String> buf = new ArrayList <String> (BUFLEN);
/** Main method */
public static void main (String[] param) {
int producer1_tick = 5000; //millisec
int producer2_tick = 7000; //millisec
int consumer1_tick = 3000; //millisec
System.out.println ("Buffer capacity: " + BUFLEN);
Producer producer1 = new Producer (producer1_tick, "Pro1");
Producer producer2 = new Producer (producer2_tick, "Pro2");
Consumer consumer1 = new Consumer (consumer1_tick, "Con1");
} // main
} // RunnableCP5
/** Producer. */
class Producer implements Runnable {
/** producing thread */
Thread pthread;
/** time to produce an item in milliseconds */
int tick;
/** producer label */
String name;
/** producer thread constructor */
Producer (int i, String s) {
pthread = new Thread (this); // "this" is Runnable
tick = i;
name = s;
pthread.start();
}
/** producer thread content */
public void run() {
try {
while (true) { // infinite loop
produce(); // produce an item after each tick
Thread.sleep (tick);
}
}
catch (InterruptedException e) {
}
} // run
/** producing process */
private void produce()
throws InterruptedException {
synchronized (RunnableCP5.buf) {
while (RunnableCP5.buf.size() >= RunnableCP5.BUFLEN) {
RunnableCP5.buf.wait(); // buffer is full, wait
}
RunnableCP5.buf.add ("(" + name + " > " +
new Date().toString() + ")"); // timestamp
System.out.println (name + " > " +
RunnableCP5.buf.get (RunnableCP5.buf.size()-1) +
" " + tick + " " + RunnableCP5.buf.size());
RunnableCP5.buf.notifyAll();
} // end of critical section
} // produce
} // Producer
/** Consumer. */
class Consumer implements Runnable {
/** consumer thread */
Thread cthread;
/** time to consume an item in milliseconds */
int tick;
/** consumer label */
String name;
/** consumer thread constructor */
Consumer (int i, String s) {
cthread = new Thread (this); // "this" is Runnable
tick = i;
name = s;
cthread.start();
}
/** consumer thread content */
public void run() {
try {
while (true) { // infinite loop
consume(); // consume an item after each tick
Thread.sleep (tick);
}
}
catch (InterruptedException e) {
}
} // run
/** consume an item */
private void consume()
throws InterruptedException {
synchronized (RunnableCP5.buf) {
while (RunnableCP5.buf.size() <= 0) {
RunnableCP5.buf.wait(); // buffer is empty, wait
}
String message = (String)RunnableCP5.buf.get (0);
System.out.println (name + " < " +
message + " " + tick);
RunnableCP5.buf.remove (0);
RunnableCP5.buf.notifyAll();
} // end of critical section
} // consume
} // Consumer
import java.util.*;
/** Producer-Consumer demo.
* @author Jaanus Poial
* @version 0.5
* @since 1.5
*/
public class ProdConSelective5 {
/** buffer capacity */
public static final int BUFLEN = 6;
/** shared buffer */
public static ArrayList <String> buf = new ArrayList <String> (BUFLEN);
/** Main method */
public static void main (String[] param) {
int producer1_tick = 5000; //millisec
int producer2_tick = 2000; //millisec
int consumer1_tick = 3000; //millisec
int consumer2_tick = 1000; //millisec
System.out.println ("Buffer capacity: " + BUFLEN);
Producer producer1 = new Producer (producer1_tick, "Pro1");
Producer producer2 = new Producer (producer2_tick, "Pro2");
Consumer consumer1 = new Consumer (consumer1_tick, "Con1");
SelectiveConsumer consumer2 = new SelectiveConsumer (consumer2_tick, "Con2");
} // main
} // ProdConSelective5
/** Producer. */
class Producer implements Runnable {
/** producing thread */
Thread pthread;
/** time to produce an item in milliseconds */
int tick;
/** producer label */
String name;
/** producer thread constructor */
Producer (int i, String s) {
pthread = new Thread (this); // "this" is Runnable
tick = i;
name = s;
pthread.start();
}
/** producer thread content */
public void run() {
try {
while (true) { // infinite loop
produce(); // produce an item after each tick
Thread.sleep (tick);
}
}
catch (InterruptedException e) {
}
} // run
/** producing process */
public void produce() throws InterruptedException {
synchronized (ProdConSelective5.buf) {
while (ProdConSelective5.buf.size() >= ProdConSelective5.BUFLEN) {
ProdConSelective5.buf.wait(); // buffer is full, wait
}
ProdConSelective5.buf.add ("(" + name + " > " +
new Date().toString() + ")"); // timestamp
System.out.println (name + " > " +
ProdConSelective5.buf.get (ProdConSelective5.buf.size()-1) +
" " + tick + " " + ProdConSelective5.buf.size());
ProdConSelective5.buf.notifyAll();
} // end of critical section
} // produce
} // Producer
/** Consumer. */
class Consumer implements Runnable {
/** consumer thread */
Thread cthread;
/** time to consume an item in milliseconds */
int tick;
/** consumer label */
String name;
/** consumer thread constructor */
Consumer (int i, String s) {
cthread = new Thread (this); // "this" is Runnable
tick = i;
name = s;
cthread.start();
}
/** consumer thread content */
public void run() {
try {
while (true) { // infinite loop
consume(); // consume an item after each tick
Thread.sleep (tick);
}
}
catch (InterruptedException e) {
}
} // run
/** consume an item */
public void consume() throws InterruptedException {
synchronized (ProdConSelective5.buf) {
while (ProdConSelective5.buf.size() <= 0) {
ProdConSelective5.buf.wait(); // buffer is empty, wait
}
String message = (String)ProdConSelective5.buf.get (0);
System.out.println (name + " < " +
message + " " + tick);
ProdConSelective5.buf.remove (0);
ProdConSelective5.buf.notifyAll();
} // end of critical section
} // consume
} // Consumer
/** Selective consumer, never uses "Pro2" labelled products. */
class SelectiveConsumer extends Consumer {
/** selective consumer thread constructor */
SelectiveConsumer (int i, String s) {
super (i, s);
}
/**check and consume an item */
public void consume() throws InterruptedException {
synchronized (ProdConSelective5.buf) {
while (ProdConSelective5.buf.size() <= 0) {
ProdConSelective5.buf.wait(); // buffer is empty, wait
}
String message = (String)ProdConSelective5.buf.get (0);
if (message.startsWith ("(Pro2")) {
System.out.println ("I do not use " + message);
ProdConSelective5.buf.wait();
} else {
System.out.println (name + " < " +
message + " " + tick);
ProdConSelective5.buf.remove (0); // consume
ProdConSelective5.buf.notifyAll();
}
} // end of critical section
} // consume
} // SelectiveConsumer
import java.applet.Applet; // our clock will be an applet
import java.awt.*;
import java.awt.event.*;
import java.util.Date; // new Date() is used to return the current time
/** Thread and Applet put together.
* @author Jaanus Poial
* @version 0.2
* @since 1.2
*/
public class Clock extends Applet implements Runnable {
/** clock thread */
private Thread thread = null;
/** one tick in milliseconds */
int tick = 1000;
/** is the clock suspended? */
private boolean suspended;
/** our clock has to implement the Runnable interface */
public void run() {
while (true) { // run forever
try {
Thread.sleep (tick); // sleep time is in milliseconds
synchronized (this) {
while (suspended) {
wait();
}
} // end of critical section
}
catch (InterruptedException e) {
}
repaint(); // renew the clock state
}
} // run
/** screen drawing to output the result */
public void paint (Graphics screen) {
screen.drawString (new Date().toString(), 50, 25);
} // paint
/** Applet init */
public void init() {
if (thread == null) {
thread = new Thread (this);
thread.start();
}
} // init
/** Applet start */
public synchronized void start() {
suspended = false;
notifyAll();
} // start
/** Applet stop */
public synchronized void stop() {
suspended = true;
notifyAll();
} // stop
/** Applet destroy, hardly ever called */
public void destroy() {
if (thread != null) {
thread.interrupt();
thread = null;
}
} // destroy
// ------------------ end of important part -----------------------------
/** Applet appears to be Serializable */
private static final long serialVersionUID = -8564370944529496313L;
/** Clock can be used also as an application */
public static void main (String[] param) {
Frame myFrame = new Frame ("I made this clock");
myFrame.setSize (350,80);
Clock myClock = new Clock(); // Runnable Applet
myFrame.add (myClock);
myFrame.setVisible (true);
myClock.init();
myClock.start();
myFrame.addWindowListener (new WindowAdapter () {
public void windowClosing (WindowEvent e) {
((Clock)((Frame)e.getWindow()).getComponent (0)).stop();
((Clock)((Frame)e.getWindow()).getComponent (0)).destroy();
System.exit (0);
}
} );
} // main
} // Clock