Heim > Java > javaLernprogramm > Ausführliche Erläuterung der Verwendung von Multithreading in Java

Ausführliche Erläuterung der Verwendung von Multithreading in Java

黄舟
Freigeben: 2017-09-08 11:15:15
Original
1236 Leute haben es durchsucht

Dieser Artikel enthält hauptsächlich relevante Informationen zur detaillierten Verwendung von Java-Multithreading. Ich hoffe, dass dieser Artikel allen Freunden in Not helfen kann.

Detaillierte Einführung in die Verwendung von Java-Multithreading -Threading.

Die umfassendste Analyse der Java-Multithreading-Nutzung. Wenn Sie den Multithreading-Mechanismus von Java noch nicht eingehend untersucht haben, kann Ihnen dieser Artikel dabei helfen, die Prinzipien besser zu verstehen Verwendung von Java-Multithreading.

1. Einen Thread erstellen

Es gibt zwei Möglichkeiten, einen Thread in Java zu erstellen: mit der Thread-Klasse und mit der Runnable-Schnittstelle. Wenn Sie die Runnable-Schnittstelle verwenden, müssen Sie eine Thread-Instanz erstellen. Unabhängig davon, ob Sie einen Thread über die Thread-Klasse oder die Runnable-Schnittstelle erstellen, müssen Sie daher eine Instanz der Thread-Klasse oder ihrer Unterklasse erstellen. Thread-Konstruktor:


public Thread( );
public Thread(Runnable target);
public Thread(String name);
public Thread(Runnable target, String name);
public Thread(ThreadGroup group, Runnable target);
public Thread(ThreadGroup group, String name);
public Thread(ThreadGroup group, Runnable target, String name);
public Thread(ThreadGroup group, Runnable target, String name, long stackSize);
Nach dem Login kopieren

Methode 1: Erben Sie die Thread-Klasse und überschreiben Sie die Ausführungsmethode


public class ThreadDemo1 {
   public static void main(String[] args){
     Demo d = new Demo();
     d.start();
     for(int i=0;i<60;i++){
       System.out.println(Thread.currentThread().getName()+i);
     }

   }
 }
 class Demo extends Thread{
   public void run(){
     for(int i=0;i<60;i++){
       System.out.println(Thread.currentThread().getName()+i);
     }
   }
 }
Nach dem Login kopieren

Methode 2:


public class ThreadDemo2 {
  public static void main(String[] args){
    Demo2 d =new Demo2();
    Thread t = new Thread(d);
    t.start();
    for(int x=0;x<60;x++){
      System.out.println(Thread.currentThread().getName()+x);
    }
  }
}
class Demo2 implements Runnable{
  public void run(){
    for(int x=0;x<60;x++){
      System.out.println(Thread.currentThread().getName()+x);
    }
  }
}
Nach dem Login kopieren

2. Der Lebenszyklus von Fäden

So wie Menschen Geburt, Alter, Krankheit und Tod, Threads müssen auch den Anfang durchlaufen. Es gibt vier verschiedene Zustände: (Warten), Laufen, Suspendiert und Stoppen. Diese vier Zustände können durch Methoden in der Thread-Klasse gesteuert werden. Die Methoden, die sich auf diese vier Zustände in der Thread-Klasse beziehen, sind unten aufgeführt.


// 开始线程
publicvoid start( );
publicvoid run( );
// 挂起和唤醒线程
publicvoid resume( );   // 不建议使用
publicvoid suspend( );  // 不建议使用
publicstaticvoid sleep(long millis);
publicstaticvoid sleep(long millis, int nanos);
// 终止线程
publicvoid stop( );    // 不建议使用
publicvoid interrupt( );
// 得到线程状态
publicboolean isAlive( );
publicboolean isInterrupted( );
publicstaticboolean interrupted( );
// join方法
publicvoid join( ) throws InterruptedException;
Nach dem Login kopieren

Der Thread führt den Code in der Ausführungsmethode nicht unmittelbar nach seiner Einrichtung aus, sondern befindet sich im Wartezustand. Wenn sich der Thread im Wartezustand befindet, können Sie über die Methoden der Thread-Klasse verschiedene Attribute des Threads festlegen, z. B. die Priorität des Threads (setPriority), den Thread-Namen (setName) und den Thread-Typ (setDaemon).

Wenn die Startmethode aufgerufen wird, beginnt der Thread mit der Ausführung des Codes in der Run-Methode. Der Thread wechselt in den laufenden Zustand. Sie können die isAlive-Methode der Thread-Klasse verwenden, um festzustellen, ob der Thread ausgeführt wird. Wenn sich der Thread im laufenden Zustand befindet, gibt isAlive „true“ zurück. Wenn isAlive „false“ zurückgibt, befindet sich der Thread möglicherweise im Wartezustand oder im gestoppten Zustand. Der folgende Code demonstriert den Wechsel zwischen den drei Zuständen Thread-Erstellung, Ausführung und Stopp und gibt den entsprechenden isAlive-Rückgabewert aus.

Sobald ein Thread mit der Ausführung der Ausführungsmethode beginnt, wird er nicht beendet, bis die Ausführungsmethode abgeschlossen ist. Während der Ausführung des Threads können Sie die Thread-Ausführung jedoch über zwei Methoden vorübergehend stoppen. Diese beiden Methoden sind Suspend und Sleep. Nachdem Sie einen Thread mit Suspend angehalten haben, können Sie ihn über die Resume-Methode aktivieren. Nachdem der Thread mit Sleep in den Ruhezustand versetzt wurde, kann er sich erst nach der festgelegten Zeit im Bereitschaftszustand befinden (nachdem der Thread-Ruhezustand endet, wird der Thread möglicherweise nicht sofort ausgeführt, sondern wechselt nur in den Bereitschaftszustand und wartet auf die Planung durch das System). .

Bei der Verwendung der Schlafmethode sind zwei Punkte zu beachten:

1. Eine der überladenen Formen kann nicht nur Millisekunden, sondern auch Nanosekunden festlegen. 1.000.000 Nanosekunden entsprechen 1 Millisekunde. Allerdings ist die Java Virtual Machine auf den meisten Betriebssystemplattformen nicht auf Nanosekunden genau. Wenn daher Nanosekunden für den Ruhezustand eingestellt sind, verwendet die Java Virtual Machine die Millisekunde, die diesem Wert am nächsten kommt.

2. Bei Verwendung der Schlafmethode müssen Würfe oder Versuche{…}Fänge{…} verwendet werden. Da die run-Methode keine Würfe verwenden kann, können Sie nur try{…}catch{…} verwenden. Wenn der Thread schläft und die Interrupt-Methode zum Unterbrechen des Threads verwendet wird, löst Sleep eine InterruptedException aus. Die Schlafmethode ist wie folgt definiert:


publicstaticvoid sleep(long millis) throws InterruptedException
publicstaticvoid sleep(long millis, int nanos) throws InterruptedException
Nach dem Login kopieren

Es gibt drei Möglichkeiten, einen Thread zu beenden.

1. Verwenden Sie das Exit-Flag, um den Thread normal zu beenden, dh der Thread wird beendet, wenn die Ausführungsmethode abgeschlossen ist.

2. Verwenden Sie die Stop-Methode, um den Thread zwangsweise zu beenden (diese Methode wird nicht empfohlen, da das Stoppen ebenso wie das Anhalten und Fortsetzen zu unvorhersehbaren Ergebnissen führen kann).

3. Verwenden Sie die Interrupt-Methode, um den Thread zu unterbrechen.

1. Verwenden Sie das Exit-Flag, um den Thread zu beenden.

Wenn die Ausführungsmethode ausgeführt wird, wird der Thread beendet. Aber manchmal endet die Ausführungsmethode nie. Verwenden Sie Threads beispielsweise in Serverprogrammen, um Client-Anfragen oder andere Aufgaben zu überwachen, die eine zyklische Verarbeitung erfordern. In diesem Fall werden diese Aufgaben normalerweise in einer Schleife, beispielsweise einer While-Schleife, platziert. Wenn Sie möchten, dass die Schleife ewig läuft, können Sie while(true){…} verwenden, um damit umzugehen. Wenn Sie jedoch möchten, dass die While-Schleife unter bestimmten Bedingungen beendet wird, besteht die direkteste Möglichkeit darin, ein boolesches Flag zu setzen und dieses Flag auf true oder false zu setzen, um zu steuern, ob die While-Schleife beendet wird. Nachfolgend finden Sie ein Beispiel für das Beenden eines Threads mithilfe des Exit-Flags.

Die Funktion der Join-Methode besteht darin, asynchrone Ausführungsthreads in synchrone Ausführung umzuwandeln. Das heißt, wenn die Startmethode der Thread-Instanz aufgerufen wird, kehrt diese Methode sofort zurück. Wenn Sie nach dem Aufruf der Startmethode einen von diesem Thread berechneten Wert verwenden müssen, müssen Sie die Join-Methode verwenden. Wenn Sie die Join-Methode nicht verwenden, gibt es keine Garantie dafür, dass der Thread ausgeführt wird, wenn eine Anweisung nach der Startmethode ausgeführt wird. Nach Verwendung der Join-Methode setzt das Programm die Ausführung erst fort, wenn dieser Thread beendet wird. Der folgende Code demonstriert die Verwendung von Join.

3. Multi-Thread-Sicherheitsprobleme

问题原因:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没执行完,另一个线程参与进来执行,导致共享数据的错误。

解决办法:对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不执行。

同步代码块:


public class ThreadDemo3 {
  public static void main(String[] args){
    Ticket t =new Ticket();
    Thread t1 = new Thread(t,"窗口一");
    Thread t2 = new Thread(t,"窗口二");
    Thread t3 = new Thread(t,"窗口三");
    Thread t4 = new Thread(t,"窗口四");
    t1.start();
    t2.start();
    t3.start();
    t4.start();
  }
}
class Ticket implements Runnable{
  private int ticket =400;
  public void run(){
    while(true){
      synchronized (new Object()) {
        try {
          Thread.sleep(1);
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
        if(ticket<=0)
          break;
        System.out.println(Thread.currentThread().getName()+"---卖出"+ticket--);
      }
    }
  }
}
Nach dem Login kopieren

同步函数


public class ThreadDemo3 {
  public static void main(String[] args){
    Ticket t =new Ticket();
    Thread t1 = new Thread(t,"窗口一");
    Thread t2 = new Thread(t,"窗口二");
    Thread t3 = new Thread(t,"窗口三");
    Thread t4 = new Thread(t,"窗口四");
    t1.start();
    t2.start();
    t3.start();
    t4.start();
  }
}
class Ticket implements Runnable{
  private int ticket = 4000;
  public synchronized void saleTicket(){
    if(ticket>0)
      System.out.println(Thread.currentThread().getName()+"卖出了"+ticket--);

  }
  public void run(){
    while(true){
      saleTicket();
    }
  }
}
Nach dem Login kopieren

同步函数锁是this 静态同步函数锁是class

线程间的通信


public class ThreadDemo3 {
  public static void main(String[] args){
    class Person{
      public String name;
      private String gender;
      public void set(String name,String gender){
        this.name =name;
        this.gender =gender;
      }
      public void get(){
        System.out.println(this.name+"...."+this.gender);
      }
    }
    final Person p =new Person();
    new Thread(new Runnable(){
      public void run(){
        int x=0;
        while(true){
          if(x==0){
            p.set("张三", "男");
          }else{
            p.set("lili", "nv");
          }
          x=(x+1)%2;
        }
      }
    }).start();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          p.get();
        }
      }
    }).start();
  }
}
/*
张三....男
张三....男
lili....nv
lili....男
张三....nv
lili....男
*/
Nach dem Login kopieren

修改上面代码


public class ThreadDemo3 {
   public static void main(String[] args){
     class Person{
       public String name;
       private String gender;
       public void set(String name,String gender){
         this.name =name;
         this.gender =gender;
       }
       public void get(){
         System.out.println(this.name+"...."+this.gender);
       }
     }
     final Person p =new Person();
     new Thread(new Runnable(){
       public void run(){
         int x=0;
         while(true){
           synchronized (p) {
             if(x==0){
               p.set("张三", "男");
             }else{
               p.set("lili", "nv");
             }
             x=(x+1)%2;  
           }

         }
       }
     }).start();
     new Thread(new Runnable(){
       public void run(){
         while(true){
           synchronized (p) {
             p.get();
           }
         }
       }
     }).start();
   }

 }
 /*
 lili....nv
 lili....nv
 lili....nv
 lili....nv
 lili....nv
 lili....nv
 张三....男
 张三....男
 张三....男
 张三....男
 */
Nach dem Login kopieren

等待唤醒机制


/*
 *线程等待唤醒机制
 *等待和唤醒必须是同一把锁 
 */
public class ThreadDemo3 {
  private static boolean flags =false;
  public static void main(String[] args){
    class Person{
      public String name;
      private String gender;
      public void set(String name,String gender){
        this.name =name;
        this.gender =gender;
      }
      public void get(){
        System.out.println(this.name+"...."+this.gender);
      }
    }
    final Person p =new Person();
    new Thread(new Runnable(){
      public void run(){
        int x=0;
        while(true){
          synchronized (p) {
            if(flags)
              try {
                p.wait();
              } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              };
            if(x==0){
              p.set("张三", "男");
            }else{
              p.set("lili", "nv");
            }
            x=(x+1)%2;
            flags =true;
            p.notifyAll();
          }
        }
      }
    }).start();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          synchronized (p) {
            if(!flags)
              try {
                p.wait();
              } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              };
            p.get();
            flags =false;
            p.notifyAll();
            }
        }
      }
    }).start();
  }
}
Nach dem Login kopieren

生产消费机制一


public class ThreadDemo4 {
  private static boolean flags =false;
  public static void main(String[] args){
    class Goods{
      private String name;
      private int num;
      public synchronized void produce(String name){
        if(flags)
          try {
            wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        this.name =name+"编号:"+num++;
        System.out.println("生产了...."+this.name);
        flags =true;
        notifyAll();
      }
      public synchronized void consume(){
        if(!flags)
          try {
            wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        System.out.println("消费了******"+name);
        flags =false;
        notifyAll();
      }

    }
    final Goods g =new Goods();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          g.produce("商品");
        }
      }
    }).start();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          g.consume();
        }
      }
    }).start();
  }
}
Nach dem Login kopieren

生产消费机制2


public class ThreadDemo4 {
  private static boolean flags =false;
  public static void main(String[] args){
    class Goods{
      private String name;
      private int num;
      public synchronized void produce(String name){
        while(flags)
          try {
            wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        this.name =name+"编号:"+num++;
        System.out.println(Thread.currentThread().getName()+"生产了...."+this.name);
        flags =true;
        notifyAll();
      }
      public synchronized void consume(){
        while(!flags)
          try {
            wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        System.out.println(Thread.currentThread().getName()+"消费了******"+name);
        flags =false;
        notifyAll();
      }

    }
    final Goods g =new Goods();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          g.produce("商品");
        }
      }
    },"生产者一号").start();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          g.produce("商品");
        }
      }
    },"生产者二号").start();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          g.consume();
        }
      }
    },"消费者一号").start();
    new Thread(new Runnable(){
      public void run(){
        while(true){
          g.consume();
        }
      }
    },"消费者二号").start();
  }
}
/*
消费者二号消费了******商品编号:48049
生产者一号生产了....商品编号:48050
消费者一号消费了******商品编号:48050
生产者一号生产了....商品编号:48051
消费者二号消费了******商品编号:48051
生产者二号生产了....商品编号:48052
消费者二号消费了******商品编号:48052
生产者一号生产了....商品编号:48053
消费者一号消费了******商品编号:48053
生产者一号生产了....商品编号:48054
消费者二号消费了******商品编号:48054
生产者二号生产了....商品编号:48055
消费者二号消费了******商品编号:48055
*/
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonAusführliche Erläuterung der Verwendung von Multithreading in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage