Threads
Процеси и нишки
Мultiprocessing- две или повече програми, които се изпълняват "видимо" конкурентно под контрола на операционната система. Програмите нямат никаква връзка помежду си освен факта че се стартират и изпълняват едновременно. |
Прилага се от операционната система и в рамките на програмата не е необходимо да се взимат никакви мерки.
Multithreading - две или повече задачи, които се изпълняват "видимо" паралелно в рамките на една и съща програма. Понякога се наричат "леки" (lightweight ) процеси |
Въпреки че се нуждае от поддръжката на операционната система, се прилага и изпълнява от самата програма. необходимо е специално проектиране и планиране на програмата.
Особености
Нишките в Java са обекти от клас Thread който е част от пакета java.lang.
При създаването на нова нишка е необходимо да се предефинира методът run(), като цялата функционалност на нишката се вгражда в този метод.
Методът run() може да вика други методи.
Нишката се стартира чрез извикването на start() метода на съответния обект.
Методът start() от своя страна вика run() метода и се грижи за изпълняването на всички допълнителни необходими задачи.
Нито един от тези методи няма параметри.
В една програма могат да се използват много различни Thread класа и много различни обекти от един и същи Thread клас.
Всеки от тези класове има свой собствен run() метод, който е независим от run() методите на останалите класове
o
Класът java.
lang. Thread позволява
създаването
на нови
нишки (threads) |
Под - клас
на Thread
o Метод 1 : подклас на Thread class Proc1 extends
Thread { |
Наследяване
на Runnable
o Метод 2 : клас наследяващ Runnable class Proc2 implements
Runnable { |
Кой
метод да
се избере ?
o Метод
1 : под-клас
на Thread
public class MyThreadApplet extends Applet implements Runnable {}
|
Състояния
Състоянието на нишката показва какво в момента тя върши и какво е в състояние да извърши. Тя може да бъде в 4 състояния: нова ( New ), работеща (Runnable), неработеща,блокирана(Blocked) и завършена (Dead ).
За всяко влизане в неработещо състояние, съществува специфичен и различен от останалите начин за връщане в работещо състояние. Всяко връщане работи само за съответния начин на влизане. Например ако тя е блокирана със sleep() връщането и в работещо състояние може да стане само след изтичането на определения брой милисекунди. Извикването на метода resume() няма да има ефект. |
Metod isAlive()
Класът Thread притежава метод isAlive(), който се използва за проверка на състоянието на нишката:
Metod getState()
Release 5.0 Въвежда
метода
Thread.getState()
.
При извикването му се връща една от следните
Thread.State стойности
:
NEW
RUNNABLE
BLOCKED
WAITING
TIMED_WAITING
TERMINATED
//: CounterA.java
// Using the Runnable interface to turn the // main class into a thread. import java.awt.*; import java.awt.event.*; import java.applet.*; public class CounterA extends Applet implements Runnable {
|
class StartL implements ActionListener {
public void actionPerformed(ActionEvent e) { if(selfThread == null){ selfThread = new Thread(CounterA.this); selfThread.start(); } runFlag = true; } } class OnOffL implements ActionListener { public void actionPerformed(ActionEvent e) { runFlag = false; } } public static void main(String[] args) { CounterA applet = new CounterA(); Frame aFrame = new Frame("CounterA"); aFrame.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } } ); aFrame.add(applet, BorderLayout.CENTER); aFrame.setSize(300,200); applet.init(); applet.start(); aFrame.setVisible(true); } } CounterA: |
//: CounterPT.java
// If you separate your thread from the main // class, you can have as many threads as you want. import java.awt.*; import java.awt.event.*; import java.applet.*; class Ticker extends Thread {
public class CounterPT extends Applet {
|
class StartL implements ActionListener {
public void actionPerformed(ActionEvent e) { if(!started) { started = true; for(int i = 0; i < s.length; i++) s[i].start(); } } } class StopL implements ActionListener{ public void actionPerformed(ActionEvent e) { for(int i=0;i<s.length;i++) s[i].stp(); } } class RestartL implements ActionListener{ public void actionPerformed(ActionEvent e){ for(int i=0; i< s.length; i++) s[i].restart(); } } public static void main(String[] args) { CounterPT applet = new CounterPT(); // This isn't an applet, so set the flag and // produce the parameter values from args: applet.isApplet = false; applet.size = (args.length == 0 ? 5 : Integer.parseInt(args[0])); Frame aFrame = new Frame("CounterPT"); aFrame.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); aFrame.add(applet, BorderLayout.CENTER); aFrame.setSize(200, applet.size * 50); applet.init(); applet.start(); aFrame.setVisible(true); } } CounterPT: |
Приоритети:
JVM управлява приоритетите чрез алгоритъм
известен като fixed priority scheduling.
Всеки thread има приоритет (право да бъде стартирана преди другите). Приоритетите се представят с цели числа в диапазона от Thread.MAX_PRIORITY (10 - най-висок) до Thread.MIN_PRIORITY (1 - най-нисък). По подразбиране всяка нишка има същия приоритет като тази, която я създала. След като бъде създадена приоритета на нишката може да се променя с метода setPriority().
Дадена нишка може да бъде в работещо състояние само ако всички нишки с по-висок приоритет са или блокирани или завършени или не стартирани. |
Ако
няколко нишки очакват ресурс изборът се прави по
round - robin метод.
След като вземе ресурсите нишката ги освобождава при следните случаи:
|
//: SimpleThread.java
public class SimpleThread extends Thread { private int countDown = 5; private String name; private static int threadCount = 0; public SimpleThread(String nameP) { name = nameP; System.out.println("Making " + name); } public void run() { for( ;countDown>0; countDown--) { System.out.println("Thread " + name + "(" + countDown + ")"+ " priority -> " + getPriority() );); } System.out.println("Thread " + name + " end"); } public static void main(String[] args) { String nameA[]={"Nick", "Marie", "George", "Isabelle", "Pierre"}; for(int i = 0; i < 5; i++) new SimpleThread(nameA[i]).start(); System.out.println("All Threads Started"); } }
|
Making Nick Making Marie Making George Making Isabelle Making Pierre All Threads Started Thread Marie(5) priority -> 5 Thread Marie(4) priority -> 5 Thread Marie(3) priority -> 5 Thread Marie(2) priority -> 5 Thread Marie(1) priority -> 5 Thread Marie end Thread Isabelle(5) priority -> 5 Thread Isabelle(4) priority -> 5 Thread Pierre(5) priority -> 5 Thread Nick(5) priority -> 5 Thread George(5) priority -> 5 Thread Isabelle(3) priority -> 5 Thread Pierre(4) priority -> 5 Thread Nick(4) priority -> 5 Thread George(4) priority -> 5 Thread Isabelle(2) priority -> 5 Thread Pierre(3) priority -> 5 Thread Nick(3) priority -> 5 Thread George(3) priority -> 5 Thread Isabelle(1) priority -> 5 Thread Pierre(2) priority -> 5 Thread Nick(2) priority -> 5 Thread George(2) priority -> 5 Thread Isabelle end Thread Pierre(1) priority -> 5 Thread Nick(1) priority -> 5 Thread George(1) priority -> 5 Thread Pierre end Thread Nick end Thread George end |
Пример с модификация на приоритета:
//: SimpleThreadPr.java public class SimpleThreadPr extends Thread { private int countDown = 5; private String name; private static int threadCount = 0; private volatile double d=0; // no optimization public SimpleThreadPr(String name, int prior) { this.name = name; setPriority(prior); System.out.println("Making " + name); } public void run() { for( ;countDown>0; countDown--) { // An expensive, interruptable operation: for(int i = 1; i < 100000; i++) d = d + (Math.PI + Math.E) / (double)i; System.out.println("Thread " + name + "(" + countDown + ")"+ " priority -> " + getPriority() ); } System.out.println("Thread " + name + " end"); } public static void main(String[] args) { String nameA[]={"Nick", "Marie", "George", "Isabelle", "Pierre","Rose","Salome"}; SimpleThreadPr st[] = new SimpleThreadPr[nameA.length]; for(int i = 0; i < nameA.length; i++) st[i] = new SimpleThreadPr(nameA[i],i<3?Thread.MAX_PRIORITY: Thread.MIN_PRIORITY); for(int i = 3; i < nameA.length; i++) st[i] .start(); System.out.println("The Threads with low priority started"); for(int i = 0; i < 3; i++) st[i] .start(); System.out.println("All Threads Started"); } }
|
Making Nick Making Marie Making George Making Isabelle Making Pierre Making Rose Making Salome The Threads with low priority started Thread Nick(5) priority -> 10 Thread Nick(4) priority -> 10 Thread Nick(3) priority -> 10 Thread Nick(2) priority -> 10 Thread Nick(1) priority -> 10 Thread Nick end Thread Marie(5) priority -> 10 Thread Marie(4) priority -> 10 Thread Marie(3) priority -> 10 Thread Marie(2) priority -> 10 Thread Marie(1) priority -> 10 Thread Marie end All Threads Started Thread George(5) priority -> 10 Thread George(4) priority -> 10 Thread George(3) priority -> 10 Thread George(2) priority -> 10 Thread George(1) priority -> 10 Thread George end Thread Pierre(5) priority -> 1 Thread Isabelle(5) priority -> 1 Thread Rose(5) priority -> 1 Thread Salome(5) priority -> 1 Thread Isabelle(4) priority -> 1 Thread Pierre(4) priority -> 1 Thread Rose(4) priority -> 1 Thread Salome(4) priority -> 1 Thread Isabelle(3) priority -> 1 Thread Pierre(3) priority -> 1 Thread Rose(3) priority -> 1 Thread Salome(3) priority -> 1 Thread Rose(2) priority -> 1 Thread Pierre(2) priority -> 1 Thread Salome(2) priority -> 1 Thread Isabelle(2) priority -> 1 Thread Rose(1) priority -> 1 Thread Rose end Thread Isabelle(1) priority -> 1 Thread Isabelle end Thread Salome(1) priority -> 1 Thread Salome end Thread Pierre(1) priority -> 1 Thread Pierre end |