1. Многопоточный код
java.lang.Thread
java.util.concurrent
Андрей Морозов, 2012
2. Состояния потока
• New – создан, но не запущен
• Running – активно использует ресурс
CPU
• Blocked, Waiting – ожидает ресурсов
или событий
• Terminated – поток перестал
использовать CPU
3. Свойства потока
• Свойства
• Id
• Name
• Priority
• Daemon
• Свойства потока не могут изменяться
после запуска
4. Расширение класса Thread
• Наследник класса Thread
переопределяет метод run()
• Создаётся экземпляр подкласса
• Вызов метода start() данного подкласса
• JVM начинает выполнение потока
вызовом метода run()
5. Пример
class SimpleCombat extends Thread {
public void run(){
//something
}
}
//запуск инструкций в новом потоке
new SimpleCombat().start();
6. Интерфейс java.lang.Runnable
• Интерфейс Runnable реализуется
классом, который должен выполняться
в отдельном потоке
• Экземпляр класса должен быть
передан конструктору класса Thread в
качестве аргумента
• Запуск потока осуществляется методом
start() класса Thread
7. Пример
public class Test implements Runnable {
private Thread selfThread = null;
private Test(){
selfThread = new Thread(this);
selfThread.start();
}
public void run() {
//something
}
}
9. Интерфейс Callable
class Task impliments // Клиентский код
Callable<String> { ExecutorService exec =
private int id; Executors.newCachedTreadPool
public Task(int id){ ();
this.id = id }
public String call(){ ArrayList<Future<String>>() results
= new
return “Result”+id ArrayList<Future<String>>()
}
} for (int I = 0; i < 10; i++){
results.add(exes.submit(new Task))
}
10. Синхронизация потоков
public class DataManager {
private static boolean ready = false;
public void sendData() {
while (!ready) {
System.out.println("Waiting for data...");
}
System.out.println("Sending data...");
}
public void prepareData() {
ready = true;
}
}
11. Cпособы синхронизации потоков
• Использовании атомарных операций и
переменных.
• Использование классов java.util.concurrent (Lock,
Semaphore, etc).
• Системная синхронизация с использованием
wait/notify.
• Системная синхронизация с использованием join
12. wait() и notify()
public class DataManager { public void prepareData() {
private static final Object monitor = synchronized (monitor) {
new Object();
System.out.println("Data
public void sendData() { prepared");
synchronized (monitor) { monitor.notifyAll();
try { }
monitor.wait(); }
} catch (InterruptedException e) }
{
e.printStackTrace();
}
System.out.println("Sending
data...");
}
}
13. Монитор
• Передача событий
– wait(time)
– notify()
– notifyAll()
• Нужно владеть блокировкой
– IllegalMonitorStateException
• Помним про возможность ложного
пробуждения
14. join()
class Sleeper extends Thread { class Joiner extends Thread {
private int duration; private Sleeper sleeper;
public Sleeper(String name, int public Joiner(String name, Sleeper
sleepTime) { sleeper) {
super(name); super(name);
duration = sleepTime; this.sleeper = sleeper;
start(); start();
} }
public void run() { public void run() {
try { try {
sleep(duration); sleeper.join();
} catch(InterruptedException e) { } catch(InterruptedException e)
print(getName()+" was interrupted."+ { print("Interrupted");
"isInterrupted(): " + isInterrupted()); }
return; print(getName() + " join completed");
} }
print(getName() + " has awakened"); }
}
}
15. join() cont.
public class Joining { Console:
public static void main(String[] args) sleeper1 was interrupted.
{ isInterrupted(): false
Sleeper joiner1 join completed
sleeper1 = new Sleeper(“sleeper1", sleeper2 has awakened
1500), joiner2 join completed
sleeper2 = new Sleeper(“sleeper2",
1500);
Joiner
joiner1 = new Joiner(“joiner1",
sleepy),
joiner2 = new Joiner(“joiner2",
grumpy);
sleeper1.interrupt();
}
}
16. Атомарность операций
• Атомарная операция - это операция,
которую не может прервать
планировщик потоков.
• В java se5 появились специальные
классы для выполнения атомарных
операций – AtomicInteger, AtomicLong,
AtomicReference и др.
18. AtomicInteger
int get() текущее значение
void set(int newValue) установка нового значения
int incrementAndGet() ++x.
long getAndIncrement() x++.
int addAndGet(int delta) –увеличивает значение на
delta и возвращает новое значение.
int getAndAdd(int delta) –увеличивает значение на
delta и возвращает предыдущее значение.
boolean compareAndSet(int expect, int update) –
установка нового значения если текущее равно
значению параметра expect.
19. CAS
Do {
old = v.get();
new = process();
} while (v.compareAndSet(old, new))
20. Synchronized
public class SynchronizationExample {
private int i;
public synchronized int synchronizedMethodGet() {
return i;
}
public int synchronizedBlockGet() {
synchronized( this ) {
return i;
}
}
}
21. Synchronized vs Volatile
synchronized -это гарантия того, что
только один поток выполняет секцию
кода в один момент времени
Volatile. Когда переменная объявлена
как volatile, любая запись её будет
осуществляться прямо в память, минуя
кеш.
22. Volatile
//код не безопасен для потоков:
myVolatileVar++;
//Этот код также может быть записан следующим
образом:
int temp = 0;
synchronize( myVolatileVar ) {
temp = myVolatileVar;
}
temp++;
synchronize( myVolatileVar ) {
myVolatileVar = temp;
}
24. Семафоры
private final Semaphore available = new
Semaphore(MAX_AVAILABLE, true);
public Object getItem() throws InterruptedException {
available.acquire();
return getNextAvailableItem();
}
public void putItem(Object x) {
available.release();
}
25. Семафоры
Конструктор
Semaphore(n, fair?) – число разрешений и
честность
Методы
acquire(n?) - получить разрешение
release(n?) - отдать разрешение
tryAquire(n?, time?) -попробовать получить
разрешение
reducePermits(n) – уменьшить количество
разрешений
drainPermits() – забрать все разрешения
26. CountDownLatch - Защелка
Возможности:
• стартуем определённое число потоков
одновременно;
• можно отследить момент окончания
нескольких потоков.
Методы:
await(time?) – ждем опускания защелки
countDown() – опускаем защелку на еденицу
getCount() – текущая высота защелки
27. CountDownLatch
public class LThread extends
Thread { // клиентский код
private final CountDownLatch CountDownLatch start = new
start; CountDownLatch(1);
public LThread(CountDownLatch for (int N = 0; N < 4; N++) {
start) { Thread t = new LThread(start);
this.start = start; t.start();
} }
public void run() { Thread.sleep(200);
start.countDown();
System.out.println( “PreRun”);
try {
start.await();
} catch (InterruptedException iex) {
} }}
28. CountDownLatch
public class SLThread extends CountDownLatch cdl = new
Thread { CountDownLatch(10);
private final CountDownLatch for (int i = 0; i < 10; i++) {
stop;
Thread t = new SLThread(cdl);
public
SLThread(CountDownLatch t.start();
stop) { }
this.stop = stop; cdl.await();
}
System.out.println(“Stopped”);
public void run() {
try {
// Некоторые действия
} finally {
stop.countDown();
}}}
29. CyclicBarrier - Барьер
Конструкторы
• CeclicBarrier(n, runnable?) – число
потоков и действие на барьере
Методы
• await(time?) – барьер
• reset() – возвращает барьер в
первоначальное состояние
• isBroken() – проверка состояния
барьера
30. Exchanger - Обменник
• Позволяет обмениваться объектами
• Конструктор
– Exchanger()
• Методы
– exchange(V x, time?) –обменяться
31. Timer
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
mainActivity();
}
};
timer.schedule(task,TIMEOUT);
32. Домашнее задание
• Взять за основу код из ДЗ к первой
лекции
• Изменить код если требуется
• Добавить возможность записи паролей
в несколько файлов одновременно