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);
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); } } }
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); } } }
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;
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
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--); } } } }
同步函数
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(); } } }
同步函数锁是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....男 */
修改上面代码
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 张三....男 张三....男 张三....男 张三....男 */
等待唤醒机制
/* *线程等待唤醒机制 *等待和唤醒必须是同一把锁 */ 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(); } }
生产消费机制一
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(); } }
生产消费机制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 */
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!