Heim >类库下载 >java类库 >Grundlegende Verwendung von Java-Multithreading

Grundlegende Verwendung von Java-Multithreading

高洛峰
高洛峰Original
2016-11-14 09:32:471849Durchsuche

1. Konzept

1.1 Prozess: Es handelt sich um eine laufende Programmausführung, die einen Ausführungspfad bzw. eine Steuereinheit darstellt.

1.2 Thread: Es handelt sich um eine unabhängige Steuereinheit im Prozess. Der Thread steuert die Ausführung des Prozesses. Es gibt mindestens einen Thread in einem Prozess.

1.3 Beispiel einer Java-VM:

Wenn Java VM startet, gibt es einen Prozess java.exe. Es gibt mindestens einen Thread im Prozess, der für die Ausführung des Java-Programms verantwortlich ist. und der von diesem Thread ausgeführte Code Existiert in der Hauptmethode. Dieser Thread wird als Hauptthread bezeichnet. Erweiterung: Tatsächlich wird JVM ausführlicher erläutert, und es gibt auch einen Thread, der für den Garbage-Collection-Mechanismus verantwortlich ist

2. Die Bedeutung von Multithreading: Verbesserung der Ausführungseffizienz

2. Multithreading erstellen

1. Die erste Möglichkeit, Multithreads zu erstellen, ist die Thread-Klasse zu erben

1.1 Definieren Sie eine Klasse zum Erben von Thread und überschreiben Sie den Lauf Methode in der Thread-Klasse zum Speichern von benutzerdefiniertem Code in run Lassen Sie den Thread in der Methode ausführen

1.2 Rufen Sie die Startmethode des Threads auf. Diese Methode hat zwei Funktionen: Starten Sie den Thread und rufen Sie die Ausführungsmethode auf

1.3 Wenn mehrere Threads ausgeführt werden, ist das Ausführungsergebnis jedes Mal das gleiche. Da mehrere Threads die Ausführungsrechte der CPU erhalten haben, wird klargestellt, dass nur ein Programm ausgeführt werden kann zu einem bestimmten Zeitpunkt. (Mit Ausnahme von Multi-Core) schaltet die CPU schnell um, um den Effekt zu erzielen, dass sie scheinbar gleichzeitig läuft. Wir können das Laufverhalten von Multithreads visualisieren, die um die Ausführungsleistung der CPU konkurrieren. Dies ist ein Merkmal von Multithreading und Zufälligkeit. Wer es ergreift, wird es ausführen. Das letzte Wort hat die CPU.

2 Der zweite Weg zum Erstellen von Multithreads, Schritte:
public class Demo extends Thread{ 
    public void run(){ 
        for (int x = 0; x < 60; x++) { 
            System.out.println(this.getName()+"demo run---"+x); 
        } 
    } 
     
    public static void main(String[] args) { 
        Demo d=new Demo();//创建一个线程 
        d.start();//开启线程,并执行该线程的run方法 
        d.run(); //仅仅是对象调用方法,而线程创建了但并没有运行 
        for (int x = 0; x < 60; x++) { 
            System.out.println("Hello World---"+x); 
        } 
    } 
 
}

2.1 Definieren Sie eine Klasse zum Implementieren der Runnable-Schnittstelle

2.2 Überschreiben Sie die Ausführungsmethode im Runnable Schnittstelle: Threads hinzufügen Der auszuführende Code wird in der Ausführungsmethode

2.3 gespeichert. Erstellen Sie ein Thread-Objekt über die Thread-Klasse

2.4. Übergeben Sie das Unterklassenobjekt der Runnable-Schnittstelle als tatsächlich Parameter an den Konstruktor der Thread-Klasse

Warum sollte das Unterklassenobjekt der Runnable-Schnittstelle an den Konstruktor von Thread übergeben werden: Da das Objekt, zu dem die benutzerdefinierte Ausführungsmethode gehört, ein Unterklassenobjekt der Runnable-Schnittstelle ist, Damit der Thread die Ausführungsmethode des angegebenen Objekts ausführen kann, muss lediglich das Objekt geklärt werden, zu dem die Ausführungsmethode gehört.

2.5 Rufen Sie die Startmethode der Thread-Klasse auf, um den Thread zu starten und aufzurufen Die Methode der Runnable-Schnittstellenunterklasse

3. Welche Implementierungsmethoden und Vererbungsmethoden gibt es?
/* 
 * 需求:简易买票程序,多个窗口同时卖票 
 */ 
public class Ticket implements Runnable { 
    private static int tick = 100; 
    Object obj = new Object(); 
    boolean flag=true; 
 
    public void run() { 
        if(flag){ 
            while (true) { 
                synchronized (Ticket.class) { 
                    if (tick > 0) { 
                        System.out.println(Thread.currentThread().getName() 
                                + "code:" + tick--); 
                    } 
                } 
            } 
        }else{ 
            while(true){ 
                show(); 
            } 
        } 
         
    } 
 
    public static synchronized void show() { 
        if (tick > 0) { 
            System.out.println(Thread.currentThread().getName() + "show:" 
                    + tick--); 
        } 
    } 
 
} 
 
class ThisLockDemo { 
    public static void main(String[] args) { 
        Ticket t = new Ticket(); 
 
        Thread t1 = new Thread(t); 
        try { 
            Thread.sleep(10); 
        } catch (Exception e) { 
            // TODO: handle exception 
        } 
        t.flag=false; 
        Thread t2 = new Thread(t); 
        //Thread t3 = new Thread(t); 
        //Thread t4 = new Thread(t); 
 
        t1.start(); 
        t2.start(); 
        //t3.start(); 
        //t4.start(); 
    } 
}

Die Implementierungsmethode vermeidet die Einschränkungen der Einzelvererbung Verwenden Sie die Implementierungsmethode beim Definieren von Threads

3.2. Erben Sie die Thread-Klasse: Der Thread-Code wird in der Ausführungsmethode der Thread-Unterklasse gespeichert

3.3. Implementieren Sie Runnable: Thread-Code wird in der gespeichert run-Methode der Unterklasse der Schnittstelle

Funktionen von Multi-Threading-Run und Start

4.1 Warum sollten wir die run-Methode überschreiben:

Die Thread-Klasse Diese Klasse definiert eine Funktion zum Speichern des vom Thread auszuführenden Codes. Die Speicherfunktion ist die Ausführungsmethode. Dies bedeutet, dass die Ausführungsmethode in der Thread-Klasse zum Speichern des auszuführenden Codes verwendet wird der Thread

5. Multi-Thread-Laufstatus

Create thread-run---sleep()/wait()--freeze---notify()--- Wake up

Thread-Run erstellen---stop()--die

Thread-Run erstellen---CPU-Ausführungsrechte nicht erfasst-vorübergehend eingefroren

Thread abrufen Objekte und ihre Namen

6.1. Threads haben ihre eigenen Standardnamen, nummeriert von 0

6.2 static Thread currentThread(): Ruft das aktuelle Thread-Objekt ab

6.3 . getName(): Holen Sie sich den Thread-Namen

6.4. Legen Sie den Thread-Namen fest: setName() oder verwenden Sie den Konstruktor

3. Multithread-Sicherheitsprobleme
public class Test extends Thread{ 
     
    Test(String name){ 
        super(name); 
    } 
     
    public void run(){ 
        for (int x = 0; x < 60; x++) { 
            System.out.println((Thread.currentThread()==this)+"..."+this.getName()+" run..."+x); 
        } 
    } 
} 
 
class ThreadTest{ 
    public static void main(String[] args) { 
        Test t1=new Test("one---"); 
        Test t2=new Test("two+++"); 
        t1.start(); 
        t2.start(); 
        t1.run(); 
        t2.run(); 
        for (int x = 0; x < 60; x++) { 
            System.out.println("main----"+x); 
        } 
    } 
}

1. Gründe für Sicherheitsprobleme beim Multithreading:

1.1. Wenn mehrere Anweisungen auf demselben Thread ausgeführt werden, um Daten gemeinsam zu nutzen, führt ein Thread nur einen Teil der mehreren Anweisungen aus, und bevor sie abgeschlossen sind, führt ein anderer Thread aus Teilnahme und Ausführung, was zu Fehlern bei gemeinsam genutzten Daten führt

1.2 Lösung: Bei mehreren Anweisungen, die mit gemeinsam genutzten Daten arbeiten, kann nur ein Thread ausgeführt werden. Während des Ausführungsprozesses können andere Threads nicht an der Ausführung teilnehmen

1.3.java bietet eine professionelle Lösung für Multithread-Sicherheitsprobleme, nämlich synchronisierte Codeblöcke:

Synchronisiert (Objekt) {Code, der synchronisiert werden muss}, Objekte sind wie Sperren und halten Sperren Threads können synchron ausgeführt werden. Auch wenn ein Thread, der keine Sperre besitzt, CPU-Ausführungsrechte erhält, kann er nicht eintreten, da die Sperre nicht erworben wurde

2 >2.1. Es müssen 2 oder mehr Threads vorhanden sein

2.2. Mehrere Threads müssen dieselbe Sperre verwenden

Der Vorteil besteht darin, dass das Sicherheitsproblem des Multithreadings gelöst wird.

2.4 Der Nachteil besteht darin, dass mehrere Threads die Sperre bestimmen müssen, was mehr Ressourcen verbraucht

2.5. Synchronisationsfunktion

Definieren Sie die Synchronisationsfunktion und ändern Sie sie mit „synced“ in der Methode

6. Synchrone Sperre

6.1 Die Funktion muss vom Objekt aufgerufen werden, dann hat die Funktion einen Verweis auf das Objekt, zu dem sie gehört, also die verwendete Sperre durch die synchronisierte Funktion ist dies
/* 
 * 需求: 
 * 银行有一个金库,有两个储户分别存300元,每次存100元,存3次 
 * 目的:该程序是否有安全问题,如果有,如何解决 
 * 如何找问题: 
 * 1.明确哪些代码是多线程代码 
 * 2.明确共享数据 
 * 3.明确多线程代码中哪些语句是操作共享数据的 
 */ 
 
public class Bank { 
 
    private int sum; 
 
    Object obj = new Object(); 
 
    //定义同步函数,在方法钱用synchronized修饰即可 
    public synchronized void add(int n) { 
        //synchronized (obj) { 
            sumsum = sum + n; 
            try { 
                Thread.sleep(10); 
            } catch (InterruptedException e) { 
                // TODO Auto-generated catch block 
                e.printStackTrace(); 
            } 
            System.out.println("sum=" + sum); 
        //} 
 
    } 
 
} 
 
class Cus implements Runnable { 
    private Bank b = new Bank(); 
 
    public void run() { 
        for (int x = 0; x < 3; x++) { 
            b.add(100); 
        } 
    } 
} 
 
class BankDemo { 
    public static void main(String[] args) { 
        Cus c = new Cus(); 
        Thread t1 = new Thread(c); 
        Thread t2 = new Thread(c); 
 
        t1.start(); 
        t2.start(); 
    } 
}

6.2. Statische Funktion Wenn die Sperre ein Klassenobjekt

ist, das statisch in den Speicher eingetragen wird, gibt es kein Objekt dieser Klasse im Speicher, aber dort muss ein Bytecode-Dateiobjekt sein, das der Klasse entspricht, Klassenname.class, und der Typ des Objekts ist Klasse

6.3 Statische Synchronisationsmethode, die verwendete Sperre ist das Bytecode-Dateiobjekt der Klasse, in der sich die Methode befindet befindet sich, Klassenname.class

7. Multithreading, Singleton-Modus-Lazy-Stil

懒汉式与饿汉式的区别:懒汉式能延迟实例的加载,如果多线程访问时,懒汉式会出现安全问题,可以使用同步来解决,用同步函数和同步代码都可以,但是比较低效,用双重判断的形式能解决低效的问题,加同步的时候使用的锁是该类锁属的字节码文件对象

/* 
 * 单例模式 
 */ 
//饿汉式 
public class Single { 
    private static final Single s=new Single(); 
    private Single(){} 
    public static Single getInstance(){ 
        return s; 
    } 
 
} 
 
//懒汉式 
class Single2{ 
    private static Single2 s2=null; 
    private Single2(){} 
    public static Single2 getInstance(){ 
        if(s2==null){ 
            synchronized(Single2.class){ 
                if(s2==null){ 
                    s2=new Single2();     
                } 
            } 
        } 
        return s2; 
    } 
} 
 
class SingleDemo{ 
    public static void main(String[] args) { 
        System.out.println("Hello World"); 
    } 
}

8.多线程-死锁

同步中嵌套同步会出现死锁

/* 
 * 需求:简易买票程序,多个窗口同时卖票 
 */ 
public class DeadTest implements Runnable { 
    private boolean flag; 
 
    DeadTest(boolean flag) { 
        this.flag = flag; 
    } 
 
    public void run() { 
        if (flag) { 
            synchronized(MyLock.locka){ 
                System.out.println("if locka"); 
                synchronized(MyLock.lockb){ 
                    System.out.println("if lockb"); 
                } 
            } 
        } else { 
            synchronized(MyLock.lockb){ 
                System.out.println("else lockb"); 
                synchronized(MyLock.locka){ 
                    System.out.println("else locka"); 
                } 
            } 
        } 
    } 
} 
 
class MyLock{ 
    static Object locka=new Object(); 
    static Object lockb=new Object(); 
} 
 
class DeadLockDemo { 
    public static void main(String[] args) { 
        Thread t1 = new Thread(new DeadTest(true)); 
        Thread t2 = new Thread(new DeadTest(false)); 
 
        t1.start(); 
        t2.start(); 
    } 
}


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn