Читайте также:
|
|
Продемонстрируем это на примере. Возьмем наш пример со случайными числами и временем и модифицируем его. Во-первых, уберем с экрана кнопку "Показать число", поскольку мы будем показывать случайные числа в цикле из процессов. Во-вторых, добавим на экран поле "Контрольная сумма". Контрольная сумма изначально у нас будет равна 0. При показе текущего случайного числа мы дополнительно будем вычислять эту контрольную сумму, прибавляя и отнимая от нее текущее случайное число. Если все в порядке, то контрольная сумма будет равна 0.
Текст программы приведен ниже
// ThreadExample6.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class ThreadExample6 extends JFrame implements Runnable {
JTextField txt1 = new JTextField(10);
JTextField txt2 = new JTextField(10);
JTextField txtTime = new JTextField(19);
JTextField txt3 = new JTextField(10);
int randValue = 0;
long numbOfRand = 0;
Thread sth = null;
JButton sbtn;
int checkSum = 0;
private boolean runFlag = false;
ThreadExample6() {
super("Знакомство с нитями (часы)");
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e) {
}
setSize(400, 300);
Container c = getContentPane();
JPanel pnm = new JPanel(new GridLayout(2, 1, 5, 5));
c.add(pnm, BorderLayout.CENTER);
JPanel pn1 = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
JPanel pn2 = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
JPanel pn3 = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
pnm.add(pn1);
pnm.add(pn2);
pnm.add(pn3);
pn1.add(new JLabel("Номер числа "));
pn1.add(txt1);
txt1.setEnabled(false);
pn2.add(new JLabel("Случайное число"));
pn2.add(txt2);
txt2.setEnabled(false);
pn3.add(new JLabel("Контрольная сумма"));
pn3.add(txt3);
txt3.setEnabled(false);
JPanel pntop = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 5));
sbtn = new JButton("Показать время");
pntop.add(sbtn);
pntop.add(txtTime);
txtTime.setEnabled(false);
txtTime.setEditable(false);
c.add(pntop, BorderLayout.NORTH);
sbtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (sth == null) {
sth = new Thread(ThreadExample6.this);
sth.start();
}
switchOnOff();
sbtn.setText(isOn()? "Остановить часы": "Показать
время");
}
});
WindowListener wndCloser = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
addWindowListener(wndCloser);
setVisible(true);
class ShowRandom extends Thread {
public void run() {
while(true) {
checkSum += randValue;
txt1.setText(String.valueOf(numbOfRand));
txt2.setText(String.valueOf(randValue));
checkSum -= randValue;
txt3.setText(String.valueOf(checkSum));
try {
Thread.sleep(200);
} catch(InterruptedException e) {
}
}
}
}
Thread[] th = new Thread[10];
for (int i = 0; i < 10; i++) {
th[i] = new ShowRandom();
th[i].start();
}
Random rnd = new Random();
for(;;numbOfRand++) {
randValue = rnd.nextInt();
try {
Thread.sleep(100);
} catch(InterruptedException e) {
}
}
}
public void run() {
while (true) {
if (runFlag) {
Date dt = new Date();
txtTime.setText(dt.toString());
} else {
txtTime.setText("");
}
try {
Thread.sleep(500);
} catch(InterruptedException e) {
}
}
}
public boolean isOn() {
return runFlag;
}
public void switchOnOff() {
runFlag =!runFlag;
}
public static void main(String[] args) {
new ThreadExample6();
}
}
В программе описан класс-нить ShowRandom, который выполняет все действия по визуализации текущего случайного числа, а также вычисляет и отображает контрольную сумму. Программа порождает десять объектов этого класса и запускает 10 нитей. Если оттранслировать и запустить эту программу, то через некоторое время ее работы мы увидим, что контрольная сумма стала ненулевой.
Причина такого эффекта в том, что запущенные нити конкурируют друг с другом за время процессора. В этой "конкурентной борьбе" участвуют Нить Диспетчеризации Событий, основная нить программы, в которой выполняется генерация случайных чисел, и 10 нитей ShowRandom. Кроме того, мы можем запустить нить для показа текущего времени. Каждая из нитей ShowRandom может быть приостановлена ОС в любой момент. При этом ОС передаст управление какой-то другой нити. В частности, она может быть прервана после выполнения
checkSum += randValue;
и перед выполнением
checkSum -= randValue;
Если при этом управление будет передано нити, генерирующей случайные числа, то прибавлено к checkSum будет одно число, а вычтено другое.
Как можно увидеть исходя из поведения программы, вероятность такого события не очень велика, но она все же сущестует.
Дата добавления: 2015-08-18; просмотров: 65 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Конкурентный доступ к ресурсам при многопоточной обработке | | | Средства синхронизации нитей в Java |