Ein Memo für mein Studium.
Ein Bereich, in dem der Wert von Variablen, generierten Instanzen, der Verlauf der aufgerufenen Methoden usw. gespeichert wird. Wo diese gespeichert sind, wird von der JVM verwaltet. Es gibt zwei Arten von Speicherbereichen
--Stapel --Haufen
Es gibt.
Der Aufrufverlauf der Methode, der Wert der in der Methode deklarierten Variablen (lokale Variable). Wenn die Methode die Verarbeitung abgeschlossen hat, werden diese Informationen vom Stapel entfernt.
Eine aus einer Klasse generierte Instanz. Wenn die Instanz von keiner Variablen mehr referenziert wird (Referenz ändern, Null zuweisen) Darüber hinaus wird es automatisch von der Garbage Collection von JVM freigegeben.
Es gibt die folgenden zwei Typen.
Es gibt zwei Methoden
--Erstellen Sie eine neue Klasse, die die Thread-Klasse erbt --Erstellen Sie eine neue Klasse, die die Runnable-Schnittstelle implementiert.
Erstellen Sie eine Instanz einer Klasse, die die Thread-Klasse erbt Rufen Sie die Startmethode dieser Instanz auf.
Es ist die Startmethode, die ausgeführt wird. In der Unterklasse, die die Thread-Klasse erbt, Überschreiben Sie die Ausführungsmethode der Thread-Klasse.
Die Ausführungsmethode wird über die Startmethode ausgeführt. Die Ergebnisse sind nicht immer gleich und ändern sich jedes Mal, wenn sie ausgeführt werden (manchmal nicht).
class MyTread extends Thread{
//HINWEIS: Der Pegel kann nicht unter den in der Oberklasse definierten Zugriffsmodifikator gesenkt werden.
//Sie können die Sichtbarkeit von Methoden, die von Thread geerbt wurden, nicht verringern
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println("MyTread.run:"+i);
}
}
}
public class SampleProgram{
public static void main(String[] args) {
MyTread mt = new MyTread();
mt.start();
for(int i = 0; i < 5; i++) {
System.out.println("main:"+i);
}
}
}
//Ergebnis
main:0
main:1
main:2
MyTread.run:0
MyTread.run:1
MyTread.run:2
MyTread.run:3
main:3
MyTread.run:4
main:4
Es ist nicht viel anders als damals, als es geerbt und hergestellt wurde.
class MyTread implements Runnable{
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println("MyTread.run:"+i);
}
}
}
public class SampleProgram{
public static void main(String[] args) {
MyTread mt = new MyTread();
Thread t = new Thread(mt);
t.start();
for(int i = 0; i < 5; i++) {
System.out.println("main:"+i);
}
}
}
Beenden Sie die Thread-Verarbeitung für einen bestimmten Zeitraum. Das Gerät ist Millisekunden. 1000: 1 Sekunde 2000: 2 Sekunden
In Mikrosekunden 1000000: 1 Sekunde
Die Thread.sleep-Methode kann eine Ausnahme vom Typ InterruptedException auslösen. Ich muss es fangen.
public class SampleProgram{
public static void main(String[] args) {
for(int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println("main:"+i);
}
}
}
//Ich habe es mit dem versucht, der die Runnable-Schnittstelle implementiert hat
class MyTread implements Runnable {
public void run() {
for(int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//TODO automatisch generierter Fangblock
e.printStackTrace();
}
System.out.println("MyTread.run:"+i);
}
}
}
public class SampleProgram{
public static void main(String[] args) {
MyTread mt = new MyTread();
Thread t = new Thread(mt);
t.start();
for(int i = 0; i < 5; i++) {
System.out.println("main:"+i);
}
}
}
join()
Sie können warten, bis der Thread verarbeitet ist.
Weil die Join-Methode eine Ausnahme vom Typ InterruptedException auslösen kann Ich muss es fangen.
Nachdem die gesamte Verarbeitung der MyTread-Klasse abgeschlossen ist, wird die Hauptverarbeitung ausgeführt.
class MyTread implements Runnable {
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println("MyTread.run:"+i);
}
}
}
public class SampleProgram{
//Lass uns das nächste Mal werfen.
public static void main(String[] args) throws InterruptedException {
MyTread mt = new MyTread();
Thread t = new Thread(mt);
t.start();
t.join();
for(int i = 0; i < 5; i++) {
System.out.println("main:"+i);
}
}
}
Wenn die Verarbeitung der Ausführungsmethode beendet wird, wird die Verarbeitung dieses Threads beendet. Hmm ... lassen wir es jetzt.
Wenn in mehreren Threads mehrere Threads denselben Variablenwert verwenden Es können Inkonsistenzen auftreten.
Das Folgende ist ein Programm, dessen Gesamtbetrag 1000000 Yen beträgt
class Bank{
static int money = 0;
static void addOneYen() {
money++;
}
}
class Customer extends Thread{
public void run() {
for(int i = 0; i < 10000; i++) {
Bank.addOneYen();
}
}
}
public class MultiThreadEx {
public static void main(String[] args) {
Customer[] customers = new Customer[100];
for(int i = 0; i < 100; i++) {
customers[i] = new Customer();
customers[i].start();
}
for(int i = 0; i < 100; i++) {
try {
customers[i].join();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Bank.money["+Bank.money+"]");
}
}
//Ergebnis
Bank.money[628887]
Weil zum Zeitpunkt der Referenzierung / Aktualisierung des aktuellen Betrags keine Konsistenz zwischen den einzelnen Bedrohungen besteht. Der Gesamtbetrag geht schief. Fügen Sie in diesem Fall vor der addOneYen-Methode "synchronized" hinzu.
static synchronized void addOneYen() {
money++;
}
Wenn Sie der Methode ein synchronisiertes Präfix voranstellen, können Sie jeweils nur einen Thread ausführen. Wenn eine Bedrohung verarbeitet wird, wartet die andere Bedrohung, bis sie an der Reihe ist.
Recommended Posts