Heim  >  Artikel  >  Java  >  Beschreiben Sie kurz die Multithread-Implementierung und die synchrone, sich gegenseitig ausschließende Kommunikation

Beschreiben Sie kurz die Multithread-Implementierung und die synchrone, sich gegenseitig ausschließende Kommunikation

Y2J
Y2JOriginal
2017-05-08 13:50:371039Durchsuche

Der folgende Editor bietet Ihnen eine kurze Diskussion über die Java-Multithreading-Implementierung und die synchrone gegenseitige Ausschlusskommunikation. Der Herausgeber findet es ziemlich gut, deshalb werde ich es jetzt mit Ihnen teilen und es allen als Referenz geben. Folgen wir dem Herausgeber, um einen Blick darauf zu werfen

Tiefgehendes Verständnis von Java-MultithreadingDieser Artikel versteht und beherrscht Multithreading hauptsächlich aus drei Aspekten:

1 . Die Implementierung von Multithreading durch die Vererbung der Thread-Klasse und die Implementierung der Runnable-Schnittstelle sowie die Ähnlichkeiten und Unterschiede.

2. So verwenden Sie synchronisiert bei der Multithread-Synchronisierung und dem gegenseitigen Ausschluss.

3. Verwendung von notify(), notifyAll() und wait() in der Multithread-Kommunikation sowie in einfachen Generator- und Verbrauchercode-Implementierungen.

Das Folgende ist eine detaillierte Erklärung von Multithreading in Java:

1: Implementierung von Multithreading

Das Erreichen von Multithreading durch Vererbung der Threa-Klasse ist hauptsächlich in die folgenden drei Schritte unterteilt:

Schritt eins: Thread erben und die run()-Methode in implementieren Thread-Klasse.

Schritt 2: Definieren Sie eine Instanz der Thread-Unterklasse.

Schritt 3: Starten Sie den Thread, indem Sie die start()-Methode der Thread-Klasse aufrufen.

Das Folgende ist eine einfache Code-Implementierung:

class myThread extends Thread{
  int n=100;
  public void run() {
    while (true) {
    if (n > 0) {
System.out.println(":"Thread.currentThread().getName()
              + "..." + n--);
        } else {
          break;
        }
      }
  }

}
public class ThreadTest {

  public static void main(String[] args) {
    myThread mythread=new myThread();
    mythread.setName("子线程");
    mythread.start();
  }

}

Mehrere Methoden, die im obigen Thread verwendet werden: Thread.currentThraed().getName()-Methode ruft den Strom ab Der Name des Threads. mythread.setName("Child-Thread"); Benennen Sie den Mythread-Thread in "Child-Thread" um.

Das Erreichen von Multithreading durch die Implementierung der Runnable-Schnittstelle ist hauptsächlich in die folgenden Schritte unterteilt:

Schritt eins: run( im Runnable implementieren Schnittstellenmethode. Generieren Sie eine Instanz von Runnable.

Schritt 2: Definieren Sie eine Thread-Klasse und übergeben Sie die obige Runnable-Instanz an die Konstruktormethode der Thread-Klasse.

Schritt 3: Starten Sie den Thread, indem Sie die start()-Methode der Thread-Klasse aufrufen.

Das Folgende ist eine einfache Code-Implementierung:

class myRunnable implements Runnable{
  int n=100;
  public void run() {
    while (true) {
    if (n > 0) {
System.out.println(":"Thread.currentThread().getName()
              + "..." + n--);
        } else {
          break;
        }
      }
  }
}
public class ThreadTest {

  public static void main(String[] args) {
    myRunnable myrunnable = new myRunnable();
    Thread mythread=new Thread(myrunnable);
    mythread.setName("子线程");
    mythread.start();
  }
}

Da Multithreading durch die Vererbung der Thread-Klasse und die Implementierung der Runnable-Methode erreicht werden kann, was sind die zwei Methoden? Was ist der Unterschied? Schauen wir uns den Unterschied zwischen den beiden anhand einer Ticketkaufkategorie an:

Angenommen, es gibt insgesamt 100 Tickets an der Kasse und der Ticketverkauf erfolgt über drei Fenster. Das bedeutet, dass wir Folgendes benötigen So öffnen Sie drei verschiedene Threads, um den Ticketkauf zu realisieren: Schauen wir uns zunächst an, wie der Ticketkauf über die Thread-Klasse realisiert wird:

class myThread extends Thread{
  int n=100;
  public void run() {
    while (true) {
    if (n > 0) {
System.out.println(":"Thread.currentThread().getName()
              + "..." + n--);
        } else {
          break;
        }
      }
  }
}
public class ThreadTest {
  public static void main(String[] args) {
    myThread m1=new myThread();
    myThread m2=new myThread();
    myThread m3=new myThread();
    m1.setName("窗口1");
    m2.setName("窗口2");
    m3.setName("窗口3");
    m1.start();
    m2.start();
    m3.start();
  }
}

Das Ergebnis ist zu lang und ich werde es nicht zeigen dass die ursprünglichen drei Fenster gemeinsam 100 Tickets gekauft haben, aber als Ergebnis hat jedes Fenster 100 Tickets gekauft. Dies ist leicht zu verstehen, da jedes Fenster ein unabhängiges Objekt mit seinem eigenen n=100 ist. Daher ist es nicht möglich, die Ticketkauffunktion über die Thread-Klasse zu implementieren. Tatsächlich wird die Thread-Methode zum Implementieren von Multithreading verwendet, bei dem der von jedem Thread ausgeführte Code nicht derselbe Code ist.

Sehen wir uns an, wie die Runnable-Schnittstelle implementiert wird, um die Ticketkauffunktion zu implementieren:

class myRunnable implements Runnable{
  int n=100;
  public void run() {
    while (true) {
    if (n > 0) {
System.out.println(":"Thread.currentThread().getName()
              + "..." + n--);
        } else {
          break;
        }
      }
  }
}
public class ThreadTest {
  public static void main(String[] args) {
    myRunnable myrunnable=new myRunnable();
    Thread m1=new Thread(myrunnable);
    Thread m2=new Thread(myrunnable);
    Thread m3=new Thread(myrunnable);
    m1.setName("窗口1");
    m2.setName("窗口2");
    m3.setName("窗口3");
    m1.start();
    m2.start();
    m3.start();
  }
}

Es ist ersichtlich, dass die oben genannten drei Threads die gleichen dieselbe ausführbare Unterklasse, also öffnen Sie einfach drei Threads, um denselben ausführbaren Code auszuführen. Es wird also keine Situation geben, in der Sie 300 Tickets kaufen müssen. Es gibt jedoch immer noch Probleme mit diesem Programm. Wir werden dieses Programm verbessern, nachdem wir über die Synchronisierung und den gegenseitigen Ausschluss nachfolgender Threads gesprochen haben.

2: So verwenden Sie synchronisiert und flüchtig bei der Multithread-Synchronisierung und beim gegenseitigen Ausschluss.

Fangen Sie nun einen Abschnitt des Problems ab, das während der Ausführung des obigen Codes aufgetreten ist, analysieren Sie, wie das Problem aufgetreten ist, und verwenden Sie dann synchronisiert, um das Problem zu lösen.

:Fenster 2…1
:Fenster 1…1
:Fenster 3…1
:Fenster 1…2
:Fenster 2…2
:Fenster 1… 3
:Fenster 3…2
:Fenster 1…4
:Fenster 2…3
:Fenster 1…5
:Fenster 3…3
:Fenster 1…6
:Fenster 2…4

Das Ergebnis des obigen Codes wird durch die Implementierung der Runnable-Schnittstelle generiert. Wie generieren das obige Fenster 1, Fenster 2 und Fenster 3 gleichzeitig 1?

  int n=100;
  public void run() {
    while (true) {
    if (n > 0) {
System.out.println(":"Thread.currentThread().getName()
              + "..." + n--);
        } else {
          break;
        }
      }

Dies ist derselbe Code, der von drei Threads ausgeführt wird. Ein Grund für das obige Ergebnis kann sein, dass die virtuelle Maschine Fenster 2 ausführt, wenn die Ausführung von Fenster 2 abgeschlossen ist und i=1 ausgegeben wird Ausgabe I. Zu diesem Zeitpunkt hat i ++ noch nicht ausgeführt, daher ist der Wert von i immer noch 1. Zu diesem Zeitpunkt erteilt die virtuelle Maschine das Ausführungsrecht an Fenster 3. Zu diesem Zeitpunkt ist die von Fenster 3 ausgegebene i-Ausgabe noch 1, und das Programm erzeugt das obige Problem. Der Hauptgrund ist, dass es eine öffentliche Variable i gibt und der Wert von i während der Programmausführung nicht synchronisiert wird. Der obige for-Schleife-Körper sollte separat ausgeführt werden, bevor andere Threads die virtuelle Maschine belegen können. Das Schlüsselwort „Synchronized“ wird verwendet, um sicherzustellen, dass ein Thread beim Ausführen eines Abschnitts öffentlicher Ressourcen nicht von anderen Threads vorbelegt wird.

Der durch die Synchronisierung geänderte Codeblock wird als synchronisierter Codeblock bezeichnet, und die durch die Synchronisierung geänderte Methode wird als synchronisierte Methode bezeichnet. Die Ticketkauffunktion wird durch Hinzufügen des folgenden synchronisierten Schlüsselworts implementiert:

class myRunnable implements Runnable {
  int n = 100;

  public void run() {
    while (true) {
      synchronized (this) {
        if (n > 0) {
          if (n % 10 == 0) {
            try {
              Thread.currentThread().sleep(10);
            } catch (InterruptedException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
            }
          }
          System.out.println(":" + Thread.currentThread().getName()
              + "..." + n--);
        } else {
          break;
        }
      }
    }
  }
}

public class ThreadTest {
  public static void main(String[] args) {
    myRunnable myrunnable = new myRunnable();
    Thread m1 = new Thread(myrunnable);
    Thread m2 = new Thread(myrunnable);
    Thread m3 = new Thread(myrunnable);
    m1.setName("窗口1");
    m2.setName("窗口2");
    m3.setName("窗口3");
    m1.start();
    m2.start();
    m3.start();
  }
}

Zu diesem Zeitpunkt kann die Ticketverkaufsfunktion korrekt abgeschlossen werden.

上面代码中synchronized(this)中的this代表的是当前的对象,因为三个线程执行的都是myRunnable 的对象,所以三个线程公用的是同一个锁,其实这个this可以用任何的对象来代替,一般我们可以 String str=new String(“”);虽然str的值为空字符串,但是也是一个对象。Synchronized实现互斥的原理是每一个对象都有一个特定的变量值,当任何一个线程调用了synchronized想要进入公共资源区时,先判断该变量的值,若该变量的值为0则可以进入公共资源区,进程在进入公共资源区之前先把对象的中的该变量值变为1,出同步区后再将该变量的值变为0,从而实现线程互斥访问公共资源。

三:多线程的通讯中的notify(),notifyAll(),及wait(),的使用方法,以及简单的生成者和消费者的代码实现。

在讲解notify(),notifyAll(),wait()之前,先看看生产者和消费者问题:生产者生产面包,消费者消费面包,但是存放面包的容器有限,生产者一次最多只能生产20个面包,消费者每次在容器中拿一个面包。通过分析可以知道,当生产者生产了20个面包之后必须停下来,等容器里的面包数目小于20个时再继续生产,消费者看到容器里面面包个数为0时也必须停下来,等到有面包时才能消费。这时候就涉及到了生产者和消费者的通信。notify()是用于唤醒等待队列中的线程,wait()用于阻塞当前线程。Notify和wait()都必须用于synchronized修饰的同步代码块或同步方法中。

下面直接看生产者消费者代码。

class Consumer implements Runnable {
  Clerk clerk;
  Consumer(Clerk clerk) {
    this.clerk = clerk;
  }
  public void run() {
    while(true)
    clerk.consumeProduct();
  }
}
class Producter implements Runnable {
  Clerk clerk;
  Producter(Clerk clerk)
  {
    this.clerk = clerk;
  }
  public void run() {
    while(true)
    clerk.addProduct();
  }
}
class Clerk {
  int product ;
  public synchronized void consumeProduct() {
    while (true) {
      if (product <= 0) {
        try {
          wait();
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      } else {
        product--;
        notifyAll();
        System.out.println("消费者消费了:" + product);
      }
    }
  }
  public synchronized void addProduct() {
    if (product > 20) {
      try {
        wait();
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    } else {
      product++;
      notifyAll();
      System.out.println("生产者生产了:" + product);
    }
  }

}
public class Test {
  public static void main(String[] args) {
    Clerk clerk=new Clerk();
    Consumer consumer=new Consumer(clerk);
    Thread c=new Thread(consumer);
    Producter producter=new Producter(clerk);
    Thread p=new Thread(producter);
    c.start();
    p.start();
  }
}

【相关推荐】

1.Java免费视频教程

2.全面解析Java注解

3.阿里巴巴Java开发手册

Das obige ist der detaillierte Inhalt vonBeschreiben Sie kurz die Multithread-Implementierung und die synchrone, sich gegenseitig ausschließende Kommunikation. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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