Pavedienu motivācija:
Pavediens ir virtuāls CPU process; to raksturo 3 sastāvdaļas:
Atšķirībā no reāliem procesiem, kam ir katram pašam savas procesora taktis, kods un dati, pavedienam pieder vienīgi savas procesora taktis, bet vispārīgajā gadījumā ir jādalās ar citiem pavedieniem gan ar kopīgu kodu, gan arī ar datiem.
1 public class ThreadTester {
2 public static void main(String args[]) {
3 HelloRunner r = new HelloRunner();
4 Thread t = new Thread(r);
5 t.start();
6 }
7 }
8
9 class HelloRunner implements Runnable {
10 int i;
11
12 public void run() {
13 i = 0;
14
15 while (true) {
16 System.out.println("Hello " + i++);
17 if ( i == 50 ) {
18 break;
19 }
20 }
21 }
22 }
Daudzpavedienu (multithreaded) programmēšana
Piemērs:
Thread t1 = new Thread(r); Thread t2 = new Thread(r);


1 public class Runner implements Runnable {
2 public void run() {
3 while (true) {
4 // veic kaut ko interesantu
5 :
6 // palaiž citus pavedienus
7 try {
8 Thread.sleep(10);
9 } catch (InterruptedException e) {
10 // ja šī pavediena miegu iztraucēja
11 // cits pavediens
12 }
13 }
14 }
15 }
1 public class Runner implements Runnable {
2 private boolean timeToQuit=false;
3
4 public void run() {
5 while ( ! timeToQuit ) {
6 ...
7 }
8 // veic resursu atbrīvošanu pirms iziet no run()
9 }
10
11 public void stopRunning() {
12 timeToQuit=true;
13 }
14 }
1 public class ThreadController {
2 private Runner r = new Runner();
3 private Thread t = new Thread(r);
4
5 public void startThread() {
6 t.start();
7 }
8
9 public void stopThread() {
10 // uzstāda karodziņu konkrētai Runner instancei
11 r.stopRunning();
12 }
13 }
1 public static void main(String[] args) {
2 Thread t = new Thread(new Runner());
3 t.start();
4 ...
5 // Dara kaut ko paralēli ar citu pavedienu
6 ...
7 // Pagaida, kamēr otrs pavediens beigs
8 try {
9 t.join();
10 } catch (InterruptedException e) {
11 // Ja cits pavediens mūs pārtrauca
12 }
13 ...
14 // Turpina viens pats
15 ...
16 }
1 public class MyThread extends Thread {
2 public void run() {
3 while (running) {
4 // dara kaut ko saturīgu
5 try {
6 sleep(100);
7 } catch (InterruptedException e) {
8 // Ja cits pavediens pārtrauca
9 }
10 }
11 }
12
13 public static void main(String args[]) {
14 Thread t = new MyThread();
15 t.start();
16 }
17 }
Implementēt Runnable interfeisu. Priekšrocības:
Mantošana no Thread:
1 public class MyStack {
2 int idx = 0;
3 char [] data = new char[6];
4
5 public void push(char c) {
6 data[idx] = c;
7 idx++;
8 }
9
10 public char pop() {
11 idx--;
12 return data[idx];
13 }
14 }



Sekojoši koda fragmenti ir ekvivalenti:
public void push(char c) {
synchronized(this) {
:
}
}
un
public synchronized void push(char c) {
:
}

No strupceļa var izvairīties sekojoši:
Alternatīvie risinājumi, ja šādu mijiedarbības funkciju nav, parasti izmantotu "busy waiting" - regulāru apjautāšanos, kas veltīgi tērē procesora ciklus.
wait() and notify() darbība balstās uz 2 pavedienu dīķiem jeb baseiniem (pool)

1 public void run() {
2 char c;
3
4 for (int i = 0; i < 200; i++) {
5 c = (char)(Math.random() * 26 +'A');
6 theStack.push(c);
7 System.out.println("Producer" + num + ": " + c);
8 try {
9 Thread.sleep((int)(Math.random() * 300));
10 } catch (InterruptedException e) {
11 // ignorē to
12 }
13 }
14 }
1 public void run() {
2 char c;
3 for (int i = 0; i < 200; i++) {
4 c = theStack.pop();
5 System.out.println("Consumer" + num + ": " + c);
6
7 try {
8 Thread.sleep((int)(Math.random() * 300));
9 } catch (InterruptedException e) { }
10
11 }
12 }
public class SyncStack {
private List buffer = new ArrayList(400);
public synchronized char pop() {
}
public synchronized void push(char c) {
}
}
1 public synchronized char pop() {
2 char c;
3 while (buffer.size() == 0) {
4 try {
5 this.wait();
6 } catch (InterruptedException e) {
7 // ignorē to
8 }
9 }
10 c = ((Character)buffer.remove(buffer.size()-1)).charValue();
11 return c;
12 }
public synchronized void push(char c) {
this.notify();
Character charObj = new Character(c);
buffer.addElement(charObj);
}
1 package mod13;
2
3 public class SyncTest {
4
5 public static void main(String[] args) {
6
7 SyncStack stack = new SyncStack();
8
9 Producer p1 = new Producer(stack);
10 Thread prodT1 = new Thread (p1);
11 prodT1.start();
12
13 Producer p2 = new Producer(stack);
14 Thread prodT2 = new Thread (p2);
15 prodT2.start();
16
17 Consumer c1 = new Consumer(stack);
18 Thread consT1 = new Thread (c1);
19 consT1.start();
20
21 Consumer c2 = new Consumer(stack);
22 Thread consT2 = new Thread (c2);
23 consT2.start();
24 }
25 }
1 package mod13;
2
3 public class Producer implements Runnable {
4 private SyncStack theStack;
5 private int num;
6 private static int counter = 1;
7
8 public Producer (SyncStack s) {
9 theStack = s;
10 num = counter++;
11 }
12
13 public void run() {
14 char c;
15 for (int i = 0; i < 200; i++) {
16 c = (char)(Math.random() * 26 +'A');
17 theStack.push(c);
18 System.out.println("Producer" + num + ": " + c);
19 try {
20 Thread.sleep((int)(Math.random() * 300));
21 } catch (InterruptedException e) {
22 // ignorē to
23 }
24 }
25 }
26 }
1 package mod13;
2
3 public class Consumer implements Runnable {
4 private SyncStack theStack;
5 private int num;
6 private static int counter = 1;
7
8 public Consumer (SyncStack s) {
9 theStack = s;
10 num = counter++;
11 }
12
13 public void run() {
14 char c;
15 for (int i = 0; i < 200; i++) {
16 c = theStack.pop();
17 System.out.println("Consumer" + num + ": " + c);
18
19 try {
20 Thread.sleep((int)(Math.random() * 300));
21 } catch (InterruptedException e) { }
22
23 }
24 }
25 }
1 package mod13;
2
3 import java.util.*;
4
5 public class SyncStack {
6 private List buffer = new ArrayList(400);
7
8 public synchronized char pop() {
9 char c;
10 while (buffer.size() == 0) {
11 try {
12 this.wait();
13 } catch (InterruptedException e) {
14 // ignorē to
15 }
16 }
17 c = ((Character)buffer.remove(buffer.size()-1)).
18 charValue();
19 return c;
20 }
21
22 public synchronized void push(char c) {
23 this.notify();
24 Character charObj = new Character(c);
25 buffer.add(charObj);
26 }
27 }
Producer2: F Consumer1: F Producer2: K Consumer2: K Producer2: T Producer1: N Producer1: V Consumer2: V Consumer1: N Producer2: V Producer2: U Consumer2: U Consumer2: V Producer1: F Consumer1: F Producer2: M Consumer2: M Consumer2: T
1 public class ControlledThread extends Thread {
2 static final int SUSP = 1;
3 static final int STOP = 2;
4 static final int RUN = 0;
5 private int state = RUN;
6
7 public synchronized void setState(int s) {
8 state = s;
9 if ( s == RUN ) {
10 notify();
11 }
12 }
13
14 public synchronized boolean checkState() {
15 while ( state == SUSP ) {
16 try {
17 wait();
18 } catch (InterruptedException e) {
19 // ignorē šo izņēmumu
20 }
21 }
22 if ( state == STOP ) {
23 return false;
24 }
25 return true;
26 }
27
28 public void run() {
29 while ( true ) {
30 // doSomething();
31
32 // Pārliecināties, ka koplietošanas dati ir konsistentā stāvoklī
33 // ja uz pavedienu gaida, vai tas iziet
34 // no run()
35 if ( !checkState() ) {
36 break;
37 }
38 }
39 }
40 }
Diskusiju tēmas