Отправляет email-рассылки с помощью сервиса Sendsay

Изучаем язык Java

  Все выпуски  

Изучаем язык Java


Java для чайников. Урок 5. Потоки (awt, thread).

Внимание!!! Новый проект "Социальная сеть проекта easypog.ru. Консультации экспертов".

 

Посмотреть пример апплета, разработанного на данном уроке, можно здесь.

 

Сегодня мы изучим понятие потока. Дело в том, что под операционной системой Windows может одновременно выполнятся несколько задач. На самом дел, конечно, одновременность кажущаяся. Каждая задача выполнятся кусочками по очереди, но так как это происходит очень быстро, то кажется, что программы выполняются одновременно. Java так же поддерживает многозадачность. Для этого в ней существует такой класс, как Theard - поток. В программе можно запустить несколько потоков, выполняющихся одновременно. Например, пока пользователь что то набирает, можно в фоновом режиме запустить какой нибудь длительный процесс расчета или загрузки данных.

Для демонстрации работы с потоками рассмотрим пример программы "гонки". В качестве гоночной дорожки у нас будут черны линии, а в качестве гонщиков - желтые овалы:

Java для чайников. Урок 5. Потоки (awt, thread).

 

Каждый гонщик - это отдельный поток. Гонщика реализует класс Racer, объявленный  от интерфейса Runnable:

 

import java.awt.Graphics;

import java.awt.Color;

 

//класс поточный, поэтому он должен наследовать интерфейс Runnable

public class Racer extends java.awt.Canvas implements Runnable {

    int position=0;

    String name;

    int stepsCount=600;

    boolean isFinished;  //флаг, что гонщик пришел на финиш

   

    //конструктор класса

    //экземпляр класса создаем по имени

    public Racer (String aName) {

        name=aName;

    }

   

    public synchronized void paint(Graphics g) {

   

        //рисуем дорожку

        g.setColor(Color.black);

        g.drawLine(0,size().height/2,size().width-170,size().height/2);

       

        //рисуем гонщика в виде желтого овала

        if(isFinished) g.setColor(Color.green); else g.setColor(Color.yellow);

        g.fillOval(position*(size().width-170)/stepsCount,0,15,size().height);

       

        //если гонщик пришел на финиш, выдадим об этом сообщение

        if(isFinished) {

            g.setColor(Color.red);

            g.drawString("Racer '"+name+"' is finished",size().width-150,size().height);

        }

       

        g.setColor(Color.red);

        g.drawString(""+position,0,size().height);

    }

   

    public void run() {

        isFinished=false;

       

        //цикл до конца гонки

        while(position<stepsCount) {

            position++;

            repaint();

           

            //останавливаем поток, что бы началось отображение

            try {

                Thread.currentThread().sleep(10);

            } catch (Exception e) {System.out.println("Exception on sleep");}

        }

        isFinished=true;

        repaint();

    }

}

 

Класс, который будет выполнятся в потоке, должен иметь метод run, которым его запускают в режим поточного выполнения. Разные потоки могут обращаться к одним и тем же данным. Дабы избежать конфликта, в Java используется синхронизация. Синхронизировать можно метод, объявив его с модификатором synchronized, либо целый блок, так же используя ключевое слово synchronized. Сегодня мы подробно на синхронизации останавливается не будем,  так как цель настоящего урока дать общие представления о потоках. Но к многопоточным приложениям мы еще вернемся и разберем их более подробно. А сейчас рассмотрим некоторые методы класса Thread:

  • start(). Запускает поток на выполнение.

  • stop(). Заканчивает выполнение потока.

  • sleep(long msec). Останавливает выполнение потока на указанное количество миллисекунд.

  • yield(). Передает ресурсов процессора другому потоку.

  • suspend(). Приостанавливает выполнение потока.

  • resume(). Возобновляет выполнение потока.

В нашем примере мы используем метод sleep, что бы приостановить на время выполнение потока, дав возможность перерисовать картинку на экране. Если этого не делать, программа просто повиснет.

И так, с классом "гонщика" понятно, тем более в тексте программы есть комментарии. Поэтому переходим к основному классу програмы:

import java.awt.Graphics;

import java.awt.GridLayout;

 

 

public class Race extends java.applet.Applet implements Runnable {

    Racer theRacers[]; //массив гонщиков

    static int count=3; //количество гонщиков

    Thread theThreads[]; //массив потоков

    Thread thisThread; //основной поток (поток, который управляет другими потоками)

    static boolean inApplet=true;

    int numberOfTheradAtStart; //в конце программы при помощи этой переменной

                               //определяем, все ли потоки прекратили существование

   

    public void init() {

        numberOfTheradAtStart=Thread.activeCount();

       

        //определяем расположение гонщиков в окне,

        //они будут добавляется один за другим

        setLayout(new GridLayout(count,1));

       

        //создаем массивы гонщиков и потоков

        theRacers=new Racer[count];

        theThreads=new Thread[count];

       

        //в цикле создаем каждый элемент массивов

        for(int i=0;i<count;i++) {

            theRacers[i]=new Racer("Racer "+i);

            theRacers[i].resize(size().width,size().height/count);

            add(theRacers[i]);

            theThreads[i]=new Thread(theRacers[i]);

        }

    }

   

    //этой процедурой мы запускаем все потоки

    public void start() {

        for(int i=0;i<count;i++) theThreads[i].start();

        thisThread=new Thread(this);

    }

   

    public void stop() {

        thisThread.stop();

    }

   

    public void run() {

   

        // цикл, пока все гонщики не закончат гонку

        while(Thread.activeCount()>numberOfTheradAtStart+2) {

            try {

                thisThread.sleep(100);

            } catch (InterruptedException e) {

                System.out.println("thisTread was interruped");

            }

        }

       

        if(inApplet) {

            stop();

            destroy();

        } else System.exit(0);

    }

   

    public static void main(String argv[]) {

        inApplet=false;

        Race theRace=new Race();

        theRace.init();

        theRace.start();

    }

}

 

Работает эта программа следующим образом:

1. Создает экземпляр самой себя.

2. Вызывает у этого экземпляра процедуру инициализации, в которой создает массив гонщиков и массив потоков. В цикле заполняет эти массивы.

3. Вызывает процедуру start(), в которой запускает потоки для гонщиков, затем создает и запускает поток для самой себя.

 

Далее все работает в потоках. У всех объектов периодически вызывается метод run. В том числе и у главного класса. В этом случае проихсодит проверка, все ли потоки завершены, если нет - поток так же на некоторое время останавливает себя, дав другим потокам поработать. Если все гонщики пришли на финиш:

Java для чайников. Урок 5. Потоки (awt, thread).

то главный поток завершает самого себя.

 

С уважением, Шуравин Александр, e-mail: megabax@rambler.ru, автор оставляет за собой право публиковать в рассылках ваши письма, если в письме прямо неоговорено нежелание его публиковать.

 

 

 


В избранное