Пакет java.lang Методы класса Math (1) Класс java.lang.Math (несколько менее точный, но более быстрый, чем класс java.lang.StrictMath) содержит большое.

Презентация:



Advertisements
Похожие презентации
ПОТОКИ Начальные сведенияПОТОКИ Начальные сведения.
Advertisements

Моделирование в электронных таблицах. Этап 4 можно реализовать с помощью табличного процессора. Конкретно с помощью программы Microsoft Excel.
Наследование Наследование – это отношение является между классами. class Person { string first_name; int birth_year;... } class Student : Person { float.
Практическое занятие 6. Функции. Большинство языков программирования используют понятия функции и процедуры. C++ формально не поддерживает понятие процедуры,
Классы Math, system, Data на языке Java Назарова К
Синтаксис языка Java. Символы и синтаксис Перевод строчки эквивалентен пробелу Регистр в именах различается.
Основные виды ресурсов и возможности их разделения.
Математические функции в РНР ABS - Возвращает модуль числа. Синтаксис: ABS ($number) Тип параметра $number может быть float или int, а тип возвращаемого.
Переменные и основные типы переменных на JAVA Выполнил учитель информатики и ИКТ МБОУ СОШ р.п. Евлашево Горелочкин Н.К.
Одномерный массив. Цель урока: познакомить учащихся с понятием одномерный массив Задачи: дать определение массива дать представление: об описании массива.
Многопоточное программирование на Java Java Advanced.
Многопоточное программирование на Java Java Advanced.
Типы данных Инна Исаева. Переменные Переменная - это как ящик, в котором можно хранить данные. Каждая переменная имеет своё имя, она служит для хранения.
МНОГОПОТОЧНОЕ ПРОГРАММИРОВАНИЕ В JAVA Пакеты java.lang java.util.concurrent.
Часть 1 Простейшая программа Программа на языке QBASIC состоит из последовательности инструкций – команд компилятору. Если в строке записано несколько.
Java. Part 2. Спецификаторы доступа public private protected не указан – доступ в пределах пакета Могут использоваться перед классами, методами, полями.
1 Контрольное зачетное задание (0, 0)(0, m-1) (n-1, 0)(n-1, m-1) Дано прямоугольное поле, расчерченное на клетки: n клеток в высоту и m клеток в ширину.
b5_java_s4
Массивы 9 класс. Основные теоретические сведения Примеры решения задач.
Основы информатики Классы Заикин Олег Сергеевич zaikin.all24.org
Транксрипт:

Пакет java.lang Методы класса Math (1) Класс java.lang.Math (несколько менее точный, но более быстрый, чем класс java.lang.StrictMath) содержит большое количество статических методов, реализующих вычисление разнообразных математических функций. Экземпляр класса создан быть не может. Вот сводка методов: doubleabs( double a )Возвращает абсолютное значение аргумента floatabs( float a )– "" – intabs( int a )– "" – longabs( long a )– "" – doubleacos( double a )Возвращает арккосинус аргумента в диапазоне от 0.0 до π doubleasin( double a )Возвращает арксинус аргумента в диапазоне от –π /2 до π /2 doubleatan( double a )Возвращает арктангенс аргумента в диапазоне от –π /2 до π /2 doubleatan2( double y, double x ) Возвращает угол из преобразования прямоугольных координат (x, y) к полярным координатам (r, угол). doublecbrt( double a )Возвращает кубический корень из значения аргумента doubleceil( double a )Возвращает самое маленькое (самое близкое к отрицательной бесконечности) целое значение в формате double, которое больше или равно значению аргумента.

Пакет java.lang Методы класса Math (2) doublecopySign( double magnitude, double sign ) Возвращает значение первого аргумента со знаком второго аргумента floatcopySign( float magnitude, float sign ) – "" – doublecos( double a )Возвращает тригонометрический косинус угла. doublecosh( double x )Возвращает гиперболический косинус угла. doubleexp( double a )Возвращает число e, возведенное в степень, заданную аргументом. doubleexpm1( double x )Возвращает exp( double a ) – 1. doublefloor( double a )Возвращает самое большое (самое близкое к положительной бесконечности) целое значение в формате double, которое меньше или равно заданного аргумента. intgetExponent( double d )Возвращает несмещенную экспоненту intgetExponent( float f )– "" – doublehypot( double x, double y )Возвращает значение sqrt( x * x + y * y ) без возможного промежуточного переполнения или потери значимости. doubleIEEEremainder( double f1, double f2 ) Вычисляет остаток согласно стандарту IEEE 754: f1 – f2 * n, где n – целое число, ближайшее к f1 / f2

Пакет java.lang Методы класса Math (3) doublelog( double a )Возвращает натуральный логарифм значения аргумента doublelog10( double a )Возвращает десятичный логарифм значения аргумента doublelog1p( double x )Возвращает натуральный логарифм значения аргумента, увеличенного на 1 doublemax( double a, double b )Возвращает большее из двух значений аргументов. floatmax( float a, float b )– "" – intmax( int a, int b )– "" – longmax( long a, long b )– "" – doublemin( double a, double b )Возвращает меньшее из двух значений аргументов. floatmin( float a, float b )– "" – intmin( int a, int b )– "" – longmin( long a, long b )– "" – doublenextAfter( double start, double direction ) Возвращает значение первого аргумента, увеличенное/уменьшенное в направлении второго аргумента на минимально возможную величину floatnextAfter( float start, double direction ) – "" –

Пакет java.lang Методы класса Math (4) doublenextUp( double d )Возвращает значение аргумента, увеличенное на минимально возможную величину floatnextUp( float f )– "" – doublepow( double a, double b ) Возвращает значение первого аргумента, возведенное в степень, равную второму аргументу. doublerandom( )Возвращает положительное псевдослучайное число, в диапазоне [0.0 – 1.0) doublerint( double a )Возвращает ближайщее к аргументу целое число в формате double longround( double a )Возвращает ближайщее к аргументу целое число в формате long intround( float a )Возвращает ближайщее к аргументу целое число в формате int doublescalb( double d, int scaleFactor ) Возвращает d * 2 в степени scaleFactor. floatscalb( float f, int scaleFactor ) – "" –

Пакет java.lang Методы класса Math (5) doublesignum( double d )Возвращает знаковую функцию от аргумента: –1.0; 0.0; 1.0 floatsignum( float f )– "" – doublesin( double a )Возвращает тригонометрический синус угла doublesinh( double x )Возвращает гиперболический синус угла doublesqrt( double a )Возвращает правильно округленный положительный квадратный корень из значения аргумента doubletan( double a )Возвращает тригонометрическую касательную (тангенс) угла. doubletanh( double x )Возвращает гиперболический тангенс угла doubletoDegrees( double angrad ) Преобразовывает угол, измеренный в радианах, к приблизительно эквивалентному углу, измеренному в градусах. doubletoRadians( double angdeg) Преобразовывает угол, измеренный в градусах, к приблизительно эквивалентному углу, измеренному в радианах. doubleulp( double d )Возвращает положительное расстояние между значением аргумента и ближайшим большим по абсолютной величине числом в формате double floatulp( float f )Возвращает положительное расстояние между значением аргумента и ближайшим большим по абсолютной величине числом в формате float

Пакет java.math Класс BigInteger (1) Вместе с классами-оболочками (и классом java.lang.Math) удобно рассмотреть классы для работы со сколь угодно большими числами из пакета java.math. Все примитивные целые типы имеют ограниченный диапазон значений. В целочисленной арифметике Java нет переполнения, целые числа приводятся по модулю, равному диапазону значений. Для того чтобы было можно производить целочисленные вычисления с любой разрядностью, имеется класс java.math.Biginteger. Он расширяет класс Number, следовательно, в нем переопределены методы doubleValue( ), f loatValue( ), intValue( ), iongVaiue( ). Методы byteValue( ) и shortValue( ) не переопределены, а прямо наследуются от класса Number (а в нем они просто возвращают результат сужающего преобразования значения intValue( ) ). Экземпляры класса хранят константу (как у класса String), соответственно, действия с объектами класса Biginteger не приводят ни к переполнению, ни к приведению по модулю. В качестве результата просто возвращается новый экземпляр класса, содержащий полный результат. Значения хранятся в двоичной форме с дополнительным кодом. Три статических константы – BigInteger.ZERO, BigInteger.ONE и BigInteger.TEN могут использоваться как нуль, единица и число 10 в любых операциях с объектами класса Biginteger. Перед выполнением любой операции числа выравниваются по длине путем распространения знакового разряда в меньшем по размеру числе.

Пакет java.lang Методы класса BigInteger (1) Большинство методов являются статическими и моделируют целочисленные операции и функции, возвращая объект класса BigInteger: static BigInteger abs ( ) возвращает объект, содержащий абсолютное значение числа, хранящегося в данном объекте this static BigInteger add( x ) возвращает результат операции this.value + х static BigInteger and( x ) возвращает результат операции this.value & х static BigInteger andNot( х ) возвращает результат операции this.value & (~х) static BigInteger divide( х ) возвращает результат операции this.value / х static BigInteger divideAndRemainder( х ) возвращает массив из двух объектов класса Biginteger, содержащих частное и остаток от деления this.value на х static BigInteger gcd( x ) возвращает наибольший общий делитель абсолютных значений объекта this.value и аргумента х static BigInteger mах( х ) наибольшее из значений объекта this.value и аргумента х static BigInteger min( x ) наименьшее из значений объекта this.value и аргумента х static BigInteger mod( х ) остаток от деления объекта this.value на аргумент х static BigInteger modInverse( х ) остаток от деления числа, обратного объекту this.value, на аргумент х

Пакет java.lang Методы класса BigInteger (2) Большинство методов класса BigInteger моделируют целочисленные операции и функции, возвращая объект класса BigInteger: static BigIntegermodPow( n, m ) остаток от деления this.value, возведенного в степень n, на m static BigIntegermultiply( х ) возвращает результат операции this.value * х static BigIntegernegate( ) перемена знака числа, хранящегося в объекте static BigIntegernot( ) возвращает результат операции –this.value static BigIntegerоr( х )оr( х ) возвращает результат операции this.value | х static BigIntegerpow( int n ) возвращает результат операции возведения числа, хранящегося в объекте, в целочисленную степень n static BigIntegerremainder( х ) возвращает результат операции this.value % х static BigIntegershiftLeft( int n ) возвращает результат операции this.value > n static BigIntegersignum( ) –1, если this.value < 0; 0, если this.value == 0; иначе 1 static BigIntegersubtract( х ) операция this.value – х static BigIntegerхоr( х ) операция this.value ^ х

Пакет java.lang Методы класса BigInteger (3) Есть специфические методы: intbitCount( )Возвращает количество бит, не совпадающих со знаковым битом intbitLength( )Возвращает минимально необходимое количество бит для представления числа (без знакового) BigIntegerclearBit( int n )Возвращает новый экземпляр, в котором указанный бит установлен в 0 intcompareTo( BigInteger val ) Сравнение собственного значения с заданным аргументом: возвращает -1 или 0 или 1 BigIntegerflipBit( int n)Возвращает новый экземпляр, в котором указанный бит инвертирован intgetLowestSetBit()Возвращает индекс первого младшего бита, равного 1 booleanisProbablePrime( int certainty ) Возвращает true, если экземпляр содержит простое (вероятно) число (или аргумент certainty

Пакет java.lang Методы класса BigInteger (4) Еще специфические методы класса BigInteger: static BigInteger probablePrime( int bitLength, Random rnd ) Возвращает возможно простое число размером bitLength бит; аргумент rnd используется для случайного выбора BigIntegersetBit( int n )Возвращает новый экземпляр, в котором указанный бит установлен в 1 booleantestBit( int n )Возвращает true если и только если указанный бит числа равен 1 byte[]toByteArray( )Преобразует число в массив байт static BigInteger valueOf( long val )Возвращает экземпляр BigInteger, содержащий значение, равное аргументу Класс Biginteger содержит также полный набор обычных методов: equals(), hashCode(), toString(), intValue(), longValue(), floatValue(), doubleValue(). В пакете java.math есть еще класс BigDecimal, имеющий похожие методы для реализации арифметических операций и ряд специфических методов. Детально этот класс здесь не рассматривается.

Пакеты java.lang и java.util.concurrent Потоки и многопоточность В момент запуска любого приложения с ним сопоставляется в точности один поток управления. Многие приложения целиком исполняются в этом единственном потоке. В платформе Java с самого начала была заложена возможность образования дополнительных потоков управления, исполняемых параллельно (одновременно или квазиодновременно) в едином адресном пространстве приложения. Средства поддержки многопоточности, обеспечивающие все более удобные и эффективные возможности, добавлялись в JDK 1.2 (класс java.lang.ThreadLocal), в JDK 1.3 (классы java.util.TimerTask и java.util.Timer), в JDK 1.5 (основные классы пакета java.util.concurrent), а затем в JDK 1.6 и 1.7 (классы и интерфейсы пакета java.util.concurrent). Вначале рассмотрим использование базовых средств платформы Java: интерфейсы: java.lang.Runnable классы java.lang.Thread java.lang.ThreadLocal java.util.TimerTask java.util.Timer java.lang.ThreadGroup

Класс java.lang.Thread Есть три возможности использования класса java.lang.Thread. 1. Можно просто создать свой дочерний класс на базе класса Thread и вызвать его метод start(). Вот пример потока, просто выдающего обратный отсчет в секундах: public static void main( String[] args ) { class ThreadTest extends Thread { int count = 4; public void run( ){ while( --count > 0 ){ System.out.println( "Wait: " + count ); try { Thread.sleep( 1000 ); } catch ( InterruptedException e ) {e.printStackTrace( ); } } System.out.println("Start!" + " Thread Id: " + Thread.currentThread( ).getId( )); } ThreadTest tt = new ThreadTest(); tt.start(); System.out.println("Main thread Id: " + Thread.currentThread( ).getId( )); } Main thread Id: 1 Wait: 3 Wait: 2 Wait: 1 Start! Thread Id: 8

Поля, конструкторы и методы класса java.lang.Thread (1) public final static int NORM_PRIORITYНормальный приоритет public final static int MAX_PRIORITYМаксимальный приоритет public final static int MIN_PRIORITYМинимальный приоритет publicThread( )Конструктор нового объекта Thread publicThread( Runnable target )Конструктор нового объекта Thread с указанием объекта, для которого будет вызываться метод run publicThread( Runnable target, String name ) Аналогично предыдущему, но дополнительно задается имя нового объекта Thread publicThread( String name )Конструктор объекта Thread с указанием его имени publicThread( ThreadGroup group, Runnable target ) Конструктор нового объекта Thread с указанием группы потока и объекта, для которого вызывается метод run publicThread( ThreadGroup group, Runnable target, String name ) Аналогично предыдущему, но дополнительно задается имя нового объекта Thread publicThread( ThreadGroup group, String name ) Конструктор нового объекта Thread с указанием группы потока и имени объекта

Методы класса java.lang.Thread (2) public static intactiveCount( )Возвращает текущее количество активных потоков в группе, к которой принадлежит поток public voidcheckAccesss( )Разрешает текущему потоку изменять этот объект Thread public intcountStackFrames( )Возвращает количество фреймов в стеке (может быть вызван только для потоков, приостановленных с помощью метода suspend( )) public static ThreadcurrentThread( )Возвращает текущий работающий поток public voiddestroy( )Принудительное завершение работы потока public static voiddumpStack( )Вывод на консоль текущего содержимого стека для отладки public static intenumerate( Thread tarray[] ) Заполняет указанный массив активными объектами Thread данной группы и всех ее подгрупп; возвращает количество заполненных элементов массива public final StringgetName( )Возвращает имя текущего потока public final intgetPriority( )Возвращает текущий приоритет потока public final ThreadGroup getThreadGroup( )Возвращает группу, к которой принадлежит поток

Поля и методы класса java.lang.Thread (3) public voidinterrupt( )Прерывание выполнения метода sleep потока public static boolean interrupted( )Проверка, прервано ли выполнение текущего потока public final boolean isAlive( )Проверка, выполняется поток или нет (может спать или ждать извещения) public final boolean isDaemon( )Проверка, является ли поток демоном Обычно потоки-демоны создаются для обслуживания некритичных задач. Виртуальная машина завершает свою работу, если завершились все потоки, не являющиеся демонами. В этот момент демоны завершаются принудительно public booleanisInterrupted( )Проверка, прервано ли выполнение данного потока public final voidjoin( )Ожидание завершения указанного потока public final voidjoin( long millis )Ожидание завершения указанного потока в течение заданного времени. Время задается в миллисекундах public final voidjoin( long millis, int nanos ) Ожидание завершения указанного потока в течение заданного времени. Время задается в миллисекундах и наносекундах public final voidresume( )Возобновление выполнения временно приостановленного потока public voidrun( )Метод вызывается неявно в том случае, если поток был создан как объект с интерфейсом Runnable

Поля и методы класса java.lang.Thread (4) public final voidsetDaemon( boolean on )Установка режима демона для потока public final voidsetName( String name )Установка имени потока public final voidsetPriority( int newPriority ) Установка приоритета потока public static voidsleep( long millis )Задержка выполнения потока на заданное время. Время задается в миллисекундах public static voidsleep( long millis, int nanos ) Задержка потока на заданное время. Время задается в миллисекундах и наносекундах public voidstart( )Инициализация потока и запуск его на выполнение, вызывается метод run public final voidstop( )Останов выполнения потока public final voidstop( Throwable obj )Аварийный останов выполнения потока с заданным исключением public final voidsuspend( )Приостанов выполнения потока public StringtoString( )Строка, представляющая объект-поток public static voidyield( )Приостанов выполнения текущего потока для того, чтобы управление было передано другому потоку

Класс java.lang.Thread, интерфейс Runnable 2. Можно реализовать интерфейс Runnable в своем классе, а затем создать объект класса Thread, передав конструктору этот объект как параметр. Этот способ используется, когда разрабатываемый класс должен быть наследником какого-либо другого класса (множественного наследования в Java нет): public static void main( String[] args ) { class ThreadTest extends java.lang.Object implements Runnable { int count = 4; public void run( ){ while( --count > 0 ){ System.out.println( "Wait: " + count ); try { Thread.sleep( 1000 ); } catch ( InterruptedException e ) {e.printStackTrace( ); } } System.out.println("Start!" + " Priority: " + Thread.currentThread( ).getPriority( ) ); } new Thread( new ThreadTest( ) ).start(); System.out.println(" Priorities: "+Thread.MIN_PRIORITY + ":" + Thread.NORM_PRIORITY + ":"+Thread.MAX_PRIORITY ); } Priorities: 1:5:10 Wait: 3 Wait: 2 Wait: 1 Start! Priority: 5

Классы java.util.TimerTask и java.util.Timer (1) 3. Часто в программе нужно выполнять какие-то действия (дальше будем их называть задачами - Task) периодически или согласно расписанию. Можно создать дочерний класс на базе класса java.util.TimerTask, а затем создать объект класса java.util.Timer, установив нужный момент (или моменты) активации задачи. Класс TimerTask является абстрактным, и служит основой для всех выполняемых по расписанию задач. Класс Timer обеспечивает создание и управление потоками, на которых выполняются эти задачи. Пример: import java.util.*; public class MyTask extends TimerTask { public void run( ) { System.out.println( "Запуск задачи" ); } В данном случае задача сводится к выведению строки на экран. Класс TimerTask реализует java.lang.Runnable интерфейс. Написанный метод должен вызываться из класса Timer.

Классы java.util.TimerTask и java.util.Timer (2) После того, как задача запрограммирована, необходимо задать расписание ее выполнения. Для этого с помощью метода schedule() создается интерфейс класса Timer: import java.util.*; … Timer timer = new Timer( ); TimerTask task = new MyTask( ); // Ждать десять секунд, прежде чем выполнить task( )... timer.schedule( task, ); // Ждать пять секунд перед первым выполнением task, // а затем выполнять каждые 10 секунд timer.schedule( task, 5000, ); Можно задать расписание четырех типов: выполнять задачу в строго отведенное время (используется объект Date); после некоторой задержки (в миллисекундах); через определенные промежутки времени; через определенные промежутки времени после заданного начального момента времени (реализуется с помощью метода scheduleAtFixedRate).

Классы java.util.TimerTask и java.util.Timer (3) Каждый объект Timer создает в точности один фоновый поток. В этом потоке могут выполняться несколько задач, каждая по своему расписанию. Большинству приложений вполне достаточно одного таймера, но в принципе можно использовать любое их количество. Остановить таймер и уничтожить его поток можно, вызвав метод cancel() объекта Timer. Нужно иметь в виду, что остановленный таймер уже не может быть перезапущен. При необходимости придется создать новый таймер и заново ввести расписание задач. Timer использует безопасные потоки, это значит, что не нужно выполнять их синхронизацию при использовании одного и того же таймера из разных потоков. Остановка задачи (и таймера, если задача является единственной у него) часто осуществляется изнутри метода run запущенной задачи. Вызов метода cancel() из метода run() гарантирует, что текущее выполнение задачи является последним. Существует возможность указать, что если по каким-то причинам выполнение задачи оказалось отсроченным по сравнению с требуемым моментом (скажем из-за уборки мусора), то два или более последующих ее выполнения будут происходить через меньшие интервалы времени для того, чтобы наверстать упущенное и войти в первоначально намеченный график. Такой режим планирования может оказаться необходимым в некоторых приложениях.

Методы классов java.util.TimerTask и java.util.Timer booleancancel( )Уничтожает текущую задачу abstract voidrun( )Замещающий метод является задачей longscheduledExecutionTime( )Возвращает запланированное время выполнения нового фактического выполнения этой задачи. Класс TimerTask: Timer( )Создает новый таймер Timer( boolean isDaemon )Создает новый таймер, связанный поток которого должен работать как демон Timer( String name )Создает новый таймер, связанный поток должен иметь указанное имя Timer( String name, boolean isDaemon ) Создает новый таймер, связанный поток должен иметь указанное имя и работать как демон Конструкторы класса Timer:

Методы класса java.util.Timer voidcancel( )Останавливает данный таймер, отменяет любые запланированные задачи intpurge( )Удаляет все отмененные задачи из очереди задач этого таймера voidschedule( TimerTask task, Date time ) Помещает указанную задачу в очередь для однократного выполнения в заданный момент времени voidschedule( TimerTask task, Date firstTime, long period ) Помещает указанную задачу в очередь для многократного выполнения через заданный интервал начиная с заданного вторым аргументом момента времени voidschedule( TimerTask task, long delay ) Помещает указанную задачу в очередь для однократного выполнения после заданной задержки voidschedule( TimerTask task, long delay, long period ) Помещает указанную задачу в очередь для многократного выполнения через заданный интервал начиная с заданной вторым аргументом задержки voidscheduleAtFixedRate( TimerTask task, Date firstTime, long period ) Помещает указанную задачу в очередь для многократного выполнения через заданный интервал начиная с заданного вторым аргументом момента времени (при задержках интервал может уменьшаться) voidscheduleAtFixedRate( TimerTask task, long delay, long period ) Помещает указанную задачу в очередь для многократного выполнения через заданный интервал начиная с заданной вторым аргументом задержки (при задержках интервал может уменьшаться)

Многопоточность и атомарность операций Основная трудность, с которой сталкиваются программисты, никогда не создававшие ранее многопоточные приложения – это неверные представления о том, как выполняются простейшие операции языка. Однопоточная программа, при запуске получает в монопольное распоряжение все ресурсы. Они используются в той последовательности, которая соответствует логике работы программы. Потоки, работающие одновременно в многопоточной системе, могут обращаться одновременно к одним и тем же ресурсам, что часто приводит к неправильной работе приложений при, казалось бы, совершенно правильной логике работы каждого отдельного потока. Простейший пример класса, в котором заложена такая некорректность, (обычно называемая "гонки данных"), приведен на следующем слайде. Некорректность вызвана тем, что операции инкремента и декремента, оказывается, не являются атомарными, т.е. неделимыми. Если бы они были такими, то программа со следующего слайда всегда выводила бы на консоль: Если вместо valueOne++; использовать valueOne += 1; то ничего принципиально не изменится. Ошибки, обусловленные гонками данных, обычно проявляются редко и совершенно бессистемно, поэтому их поиск и устранение становится чрезвычайно сложной задачей. valueOne = 0, valueTwo = 0

Гонки данных, пример class DataRacingTest{ int valueOne = 0, valueTwo = 0; public void dataRacingTest( ) { Thread threadOne = new Thread( ) { public void run() {// перед этой строкой должна быть for ( int i=0; i

Хранение данных (1) Для того, чтобы выяснить, откуда берутся гонки данных, нужно разобраться в том, как обеспечивается хранение данных приложения и его потоков. Для любого приложения виртуальная машина поддерживает основное хранилище данных (main storage), в котором сохраняются значения всех переменных и которое используется всеми потоками. Под переменными здесь понимаются поля объектов и классов, а также элементы массивов. Локальные переменные и параметры методов не могут быть доступны другим потокам, поэтому они не представляют интереса. Для каждого потока создается его собственная рабочая память (working memory), в которую перед использованием копируются значения всех переменных. Основные операции, реализуемые виртуальной машиной при работе с памятью: use – чтение значения переменной из рабочей памяти потока; assign – запись значения переменной в рабочую память потока; read – получение значения переменной из основного хранилища; load – сохранение значения переменной, прочитанного из основного хранилища, в рабочей памяти; store – передача значения переменной из рабочей памяти в основное хранилище для дальнейшего хранения; write – сохраняет в основном хранилище значение переменной, переданной командой store. Эти операции являются командами байт-кода, формируемыми компилятором, и в явном виде недоступны программисту.

Хранение данных (2) Поток, работая с любой своей переменной, регулярно применяет команды use и assign для использования ее текущего значения и присвоения нового. Кроме того, должны осуществляться действия по передаче значений в основное хранилище и из него. Они выполняются в два этапа. При получении данных сначала из основного хранилища считывается значение командой read, а затем оно сохраняется в рабочей памяти потока командой load. Эта пара команд всегда выполняется вместе именно в таком порядке, т.е. нельзя выполнить одну, не выполнив другую: { read load } use … use При отправлении данных сначала поток считывает значение из своей рабочей памяти командой store, а затем основное хранилище сохраняет его командой write. Эта пара команд также всегда выполняется вместе именно в таком порядке, т.е. нельзя выполнить одну, не выполнив другую. assign … assign { store write } Набор этих правил составлялся так, чтобы операции с памятью не допускали возможности их неверного использования, а с другой стороны, правила должны оставлять достаточное пространство для различных технологий оптимизации (регистры, очереди, кэши и т.д.).

Хранение данных (3) Исполнение последовательности команд байт-кода виртуальной машиной всегда подчиняется следующим правилам: 1. Все действия, выполняемые одним потоком, строго упорядочены, т.е. выполняются одно за другим в соответствии с порядком извлечения команд байт- кода; 2. Все действия, выполняемые с каждой переменной в основном хранилище памяти, тоже строго упорядочены, т.е. следуют одно за другим. За исключением некоторых дополнительных очевидных правил, больше никаких ограничений нет. Например, если поток изменил значение сначала одной, а затем другой переменной, то измененные данные могут быть переданы в основное хранилище в обратном порядке. В 32-битных системах действия по передаче значений между основным хранилищем и рабочей памятью потока над половинками 64-битных примитивных типов float и double тоже могут выполняться в произвольном порядке. Оба этих фактора в принципе могут создавать проблемы типа гонок данных. Поток создается с чистой рабочей памятью и должен перед использованием загрузить все необходимые переменные из основного хранилища. Любая переменная сначала создается в основном хранилище и лишь затем копируется в рабочую память потоков, которые будут ее применять. Таким образом, потоки никогда не взаимодействуют друг с другом напрямую, только через главное хранилище. Однако нет 100-процентной гарантии, что изменение значения переменной одним потоком обязательно будет "увидено" другим потоком.