Эккель Брюс
Шрифт:
// concurrency/ThreadVariations java
// Создание потоков с использованием внутренних классов.
import java.util.concurrent.*,
import static net mindview.util.Print.*;
// Используем именованный внутренний класс, class InnerThreadl {
private int countDown = 5; private Inner inner, private class Inner extends Thread { Inner(String name) { super(name); startO,
}
public void run { try {
while(true) {
print(this);
if(--countDown == 0) return; sleep(lO);
}
} catchdnterruptedException e) { »print("interrupted"):
}
}
public String toStringO {
return getNameO + ": " + countDown;
>
}
public InnerThreadKString name) { inner = new Inner(name);
Thread-0(4), Thread-КЗ), Thread-2(2), Thread-3(1),
Thread-1(5). Thread-2(4). Thread-3(3). Thread-4(2).
Thread-0(3), Thread-1(2), Thread-2(1), Thread-4(5),
Thread-0(2). Thread-Id). Thread-3(5). Thread-4(4),
Thread-Od). Thread-2(5). Thread-3(4), Thread-4(3).
// Используем безымянный внутренний класс: class InnerThread2 {
private int countDown = 5; private Thread t;
public InnerThread2(String name) { t = new Thread(name) {
public void run { try {
while(true) {
print(this).
if(--countDown == 0) return, sleep(lO).
}
} catch(InterruptedException e) {
printCsleepO interrupted");
}
}
public String toStringO {
return getNameO + ". " + countDown;
}
}:
t startO;
}
}
// Используем именованную реализацию Runnable. class InnerRunnablel {
private int countDown = 5; private Inner inner,
private class Inner implements Runnable { Thread t;
Inner(String name) {
t = new Thread(this. name); t.startO;
}
public void runO { try {
while(true) {
print(this);
if(--countDown == 0) return; Ti mellnit .MILLISECONDS. si eep( 10);
}
} catch(InterruptedException e) {
printCsleepO interrupted");
}
}
public String toStringO {
return t.getNameO + ". " + countDown;
}
}
public InnerRunnableKString name) { inner = new Inner(name),
// Используем анонимную реализацию Runnable-class InnerRunnable2 {
private int countDown = 5;
private Thread t;
public InnerRunnable2(String name) {
t = new Thread(new RunnableO { public void run { try {
while(true) {
print(this);
if(--countDown == 0) return; Ti mellnit. MI LLISECONDS. s 1 eep( 10);
}
} catchdnterruptedException e) {
printCsleepO interrupted");
}
}
public String toStringO {
return Thread.currentThreadO.getNameO + ": " + countDown;
}
}. name); t.startO;
}
}
// Отдельный метод для выполнения кода в потоке: class ThreadMethod {
private int countDown = 5; private Thread t; private String name;
public ThreadMethodCString name) { this.name = name; } public void runTaskO { if(t == null) {
t = new Thread(name) {
public void run { try {
while(true) {
print(this);
if(--countDown == 0) return; sleep(lO);
}
} catchdnterruptedException e) {
printCsleepO interrupted");
}
}
public String toStringO {
return getNameO + ": " + countDown;
}
}:
t.startO;
}
}
}
public class ThreadVariations {
public static void main(String[] args) { new InnerThreadlCInnerThreadl") ; new InnerThread2("InnerThread2"); new InnerRunnablelCInnerRunnablel");
new InnerRunnable2("InnerRunnable2"); продолжение &
new ThreadMethodC'ThreadMethod") runTaskO,
}
} ///-
InnerThreadl определяет именованный внутренний класс, производный от Thread, и создает экземпляр этого класса в конструкторе. Поступать так стоит в том случае, когда у внутреннего класса есть особые возможности (новые методы), которые могут понадобиться в других методах. Однако в большинстве случаев причина создания потока — использование функциональности класса Thread, поэтому в именованном внутреннем классе особой нужды нет. Inner-Thread2 показывает другое решение. В конструкторе создается безымянный внутренний субкласс Thread, преобразуемый восходящим преобразованием к ссылке на Thread t. Если другим методам класса понадобится обратиться к t, они смогут сделать это через интерфейс Thread, и им не нужно будет знать точный тип объекта.