Java-Threads und -Prozesse

Java-Threads und -Prozesse

Prozess

  • Konzept: ist das laufende Programm
    • Es ist eine unabhängige Einheit für das System, um Ressourcen zuzuweisen und aufzurufen
    • Jeder Prozess verfügt über einen eigenen Speicherplatz und eigene Systemressourcen

Faden

  • Konzept: Ein einzelner sequentieller Steuerungsfluss in einem Prozess ist ein Ausführungspfad
    • Einzelner Thread: Ein Prozess hat nur einen Ausführungspfad (in der Reihenfolge)
    • Multithreading: Mehrere Ausführungspfade
  • Multithread-Beispiel
    • Minesweeper: Einer zur Kontrolle der Zeit und der andere zur Kontrolle der Bestellung des Spielers, um Tickets zu verkaufen und Geld einzuzahlen usw.

Multithread-Implementierung

  • Erstens: Erben Sie die Thread-Klasse (später über die Schnittstelle implementiert).
    • Klasse definieren MyThread erbt die Thread-Klasse
    • 在MyThread类中重写run方法(Unterscheiden Sie Code, der von Threads ausgeführt werden kann)
    • Erstellen Sie ein Objekt der MyThread-Klasse
    • Thread starten
    • wichtiger Punkt
      • Schreiben Sie die Ausführungsmethode neu, da diese Methode den Thread-Ausführungscode kapselt.直接调用它的话会被当成普通方法调用
      • Der start方法Start-Thread muss aufgerufen werden, und dann wird die Ausführungsmethode des Threads von der JVM aufgerufen
      • Wenn Sie den Thread-Namen Thread.currentThread().getName()abrufen möchten, gibt es drei Möglichkeiten, um den Namen abzurufen: 1. get set-Methode (getName entspricht direkt this.getName ()), 2. Struktur mit Parametern, 3. statisch Methode currentThread () gibt einen Verweis auf den aktuellen Ausführungsthread zurück

package Thread;

public class ThreadName extends Thread{
    ThreadName(String name){
        super(name);//超类有这个带参构造则一定要传super的参数且为第一句
    }
    //@Override
    public void run() {
        for(int i=0;i<50;i++){
            System.out.println(getName()+":"+i);
        }
    }
}



package Thread;

public class ThreadNameDemo{
    public static void main(String[] args) {
        ThreadName tn1=new ThreadName("线程1");//tn1.setName("线程1")
        ThreadName tn2=new ThreadName("线程2");
        tn1.start();
        tn2.start();
        //也可以在main函数中用getName方法,但是因为测试类没有继承Thread类,所以不可以直接用getName,需要用到Thread.currentThread().getName()
    }
}
  • Zweitens, Thread-Planung

    • Java verwendet ein präemptives Planungsmodell: Geben Sie Threads mit hoher Priorität Priorität, um die CPU zu verwenden. Wenn die Threads dieselbe Priorität haben, wird einer zufällig ausgewählt
    • 但是优先级高并不一定就是一直先执行,只是该线程抢占到的CPU时间片的几率更大Sie können den gewünschten Effekt jedoch nur sehen, wenn mehr oder mehr Läufe vorhanden sind
    • Der Thread-Standardwert ist 5 und der Prioritätsbereich ist 1-10
    • Fügen Sie hier eine Bildbeschreibung ein
public class ThreadPriorityDemo {
    public static void main(String[] args) {
        ThreadPriority tp1=new ThreadPriority();
        ThreadPriority tp2=new ThreadPriority();
        tp1.setName("线程1");
        tp2.setName("线程2");
        System.out.println(tp1.getPriority());
        System.out.println(tp2.getPriority());
        tp1.setPriority(1);
        tp2.setPriority(10);
        tp1.start();
        tp2.start();
    }
}

public final int getPriority():返回线程优先级
public final void setPriority():更改此线程的优先级
  • Drei, Thread-Kontrolle
    • Fügen Sie hier eine Bildbeschreibung ein

    • Mit der Join-Methode kann der Thread die Ausführung abschließen, bevor andere Threads gestartet werden

    • Die repräsentativen Methoden zum Auslösen von InterruptedException (was darauf hinweist, dass diese Methode zwar etwas Zeit in Anspruch nimmt, aber abgebrochen werden kann) sind:

        1. java.lang.Object-Klasse wait 方法
        1. java.lang.Thread-Klasse sleep 方法
        1. java.lang.Thread-Klasse join 方法

Der Thread, der die Wartemethode ausführt, betritt den Wartebereich und wartet auf die Benachrichtigung / Benachrichtigung aller. Während der Wartezeit ist der Thread nicht aktiv.

Der Thread, der die Schlafmethode ausführt, wird暂停执行参数内所设置的时间。

Der Thread, der die Join-Methode ausführt, wartet, bis der angegebene Thread endet.

public class ThreadSleep extends  Thread{
    @Override
    public void run() {
        for(int i=0;i<100;i++){
            System.out.println(getName()+":"+i);
            try {
                Thread.sleep(1000);//让当前正在执行的线程休眠1s(暂停执行),每次执行三者各执行一次,因为ts1抢到后执行run()休眠1次,ts2抢到后也休眠1次同时抢抢到后执行调用run才开始休眠
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


public class ThreadJoinDemo {
    public static void main(String[] args) {
        ThreadJoin tj1=new ThreadJoin();
        ThreadJoin tj2=new ThreadJoin();
        ThreadJoin tj3=new ThreadJoin();
        tj1.setName("开花");
        tj2.setName("结果1");
        tj3.setName("结果2");
        tj1.start();
        try {
            tj1.join();//等待tj1执行完
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        tj2.start();
        tj3.start();

    }

}



public class ThreadDaemondemo {
    public static void main(String[] args) {
        ThreadDaemon td1=new ThreadDaemon();
        ThreadDaemon td2=new ThreadDaemon();
        td2.setName("士兵1");
        td1.setName("士兵2");
        //设置主线程为将军
        Thread.currentThread().setName("将军");
        //设置守护线程
        td1.setDaemon(true);
        td2.setDaemon(true);
        td1.start();
        td2.start();//守护线程在主线程结束后很快执行完毕但是不是立即结束
        for(int i=0;i<40;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

Obwohl der Hauptthread beim Programmstart automatisch erstellt wird, kann er von einem Thread-Objekt gesteuert werden. Dazu müssen Sie die Methode currentThread()获得它的一个引用currentThread () aufrufenThread类的公有的静态成员。

  • Drei, der Lebenszyklus des Threads
    • Fügen Sie hier eine Bildbeschreibung ein

    • Die vorherige Schlafmethode besteht also darin, dass sie blockiert, nachdem sie einmal ausgeführt wurde, und dann zurückgeht, um das Ausführungsrecht zu erhalten. Jeder der drei Threads wird einmal ausgeführt und geht dann zurück, um zu greifen, sodass es drei für eine Runde gibt.

  • Andere Implementierungen von Multithreading: (Es gibt zwei Möglichkeiten, einen neuen Ausführungsthread zu erstellen.)
    • Eins, klassifizieren 声明为 Thread 的子类. Die Unterklasse sollte die Ausführungsmethode der Thread-Klasse überschreiben. Anschließend können Sie eine Instanz der Unterklasse zuweisen und starten
    • 2. Aussage 实现 Runnable 接口的类. Diese Klasse implementiert die Ausführungsmethode. Dann können Sie eine Instanz dieser Klasse zuweisen,在创建 Thread 时作为一个参数来传递并启动
    • Die vorherigen Beispiele werden auf die erste und dann auf die zweite Weise implementiert
    • Der zweite Weg vermeidet die Einschränkungen der Java-Einzelvererbung
      • Definieren Sie eine Klasse Myrunnable, um die Runnable-Schnittstelle zu implementieren
      • Überschreiben Sie die Ausführungsmethode in der MyRunnable-Klasse
      • Erstellen Sie ein Objekt der Myrunnable-Klasse
      • Erstellen Sie ein Thread-Objekt und übergeben Sie das obige Objekt als Parameter an das Thread-Objekt
      • Thread starten
    • Gewindekonstruktionsmethode
      • Fügen Sie hier eine Bildbeschreibung ein
public class MyRunnable implements Runnable{
    //Runnable接口和Thread类没有关系不能调用Thread中的getName方法
    @Override
    public void run() {
        for(int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

public class MyRunnableDemo {
    public static void main(String[] args) {
        MyRunnable mr=new MyRunnable();
        Thread t1=new Thread(mr);//Thread t1=new Thread(mr,"线程1")
        Thread t2=new Thread(mr);//Thread t2=new Thread(mr,"线程2")起名
        t1.start();
        t2.start();
    }
}

Umfassender Fall (Mechanismus zum Sperren des gegenseitigen Ausschlussmechanismus)

  • Ticketverkauf
//第一次:出现两种问题负数票和一票多用,问题原因是线程执行的随机性
public void run() {
        while(true){
            if(ticket>0){
                try {
                    Thread.sleep(100);//通过sleep模拟出票时间
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在售出第"+ticket+"张票");
                //可能在ticket--之前t2或者t3抢到了CPU的执行权:这就是看到同一张票出现多次的原因
                //可能在t1将ticket--变成0时,t1不能再继续售票,但t2已经进来循环了,所以还可以--:这就是出现负数票的原因
                ticket--;
            }
        }
    }

  • Die Grundlage des Problems aufgrund der Zufälligkeit: Multithread-Umgebung und gemeinsam genutzte Datenressourcen sowie mehrere Anweisungsoperationen zur gemeinsamen Nutzung von Daten
  • Lösen Sie das Problem: Sperren Sie den Code, damit mehrere Anweisungen ausgeführt und Daten gemeinsam genutzt werden können, sodass jeweils nur ein Thread vorhanden ist
    • Synchronisationscodeblock: synchronized(任意对象){多条语句操作共享数据的代码块}
      (Jedes Objekt kann als Sperre angesehen werden.)
public class SellTicket implements Runnable{
    private int ticket=100;
    private Object obj=new Object();//共用一把锁
    @Override
    public void run() {
        while(true){
            synchronized (obj){
                //如果是t1先抢到执行权则t1执行到这里会把这段代码锁起来,t2、t3只能等即时t1休眠期直到t1出来代码块
                if(ticket>0){
                    try {
                        Thread.sleep(100);//通过sleep模拟出票时间
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"正在售出第"+ticket+"张票");
                    ticket--;
                }
            }
            }
    }
}
  • Vor- und Nachteile der Synchronisierung: Lösen Sie das Datensicherheitsproblem des Multithreading. Wenn jedoch viele Threads vorhanden sind, beurteilt jeder Thread die Sperre für die Synchronisierung, wodurch Ressourcen verbraucht und die Betriebseffizienz verringert werden
  • Synchronisationsmethode:修饰符 sychronized 返回值类型 方法名(方法参数){}
  • Synchrone statische Methode:修饰符 static sychronized 返回值类型 方法名(方法参数){}
    • Das gesperrte Objekt in der Synchronisationsmethode ist dieses (wenn es sich um eine statische Methode handelt, müssen Sie diese durch den Klassennamen.class ersetzen).

Ich denke du magst

Origin blog.csdn.net/Phoebe4/article/details/110749734
Empfohlen
Rangfolge