Heim  >  Artikel  >  Java  >  Zusammenfassung der Java-Wissenspunkte: Multithreading-Grundlagen

Zusammenfassung der Java-Wissenspunkte: Multithreading-Grundlagen

WBOY
WBOYnach vorne
2022-11-15 17:24:221842Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über Java und stellt hauptsächlich den relevanten Inhalt zum Multithreading vor. Mehrere Threads können gleichzeitig ausgeführt werden. Zum Beispiel: Sie können Thunder verwenden, um mehrere Dateien gleichzeitig herunterzuladen. Ich hoffe, es wird für alle hilfreich sein.

Zusammenfassung der Java-Wissenspunkte: Multithreading-Grundlagen

Empfohlenes Lernen: „Java-Video-Tutorial

1. Threadbezogene Konzepte

1. Programm: Es handelt sich um eine Reihe von Anweisungen, die in einer bestimmten Sprache geschrieben sind, um eine bestimmte Aufgabe auszuführen. Einfach ausgedrückt: ist der Code, den wir schreiben. 就是我们写的代码

2、进程:是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为 该进程分配内存空间。当我们使用迅雷,又启动了一个进程,操作系统将为迅雷分配新的内存空间。

进程是程序的一次执行过程,或是正在运行的一个程序。是动态过程:有它自身的产生、存在和消亡的过程。

3、线程:是进程创建的,是进程的实体,一个进程可以有多个线程,例如使用迅雷下载文件,迅雷相当于进程,下载的文件相当于线程。

4、单线程:同一时刻,只允许执行一个线程

5、多线程:同一时刻,可以执行多个线程。例如:使用迅雷可以同时下载多个文件。

6、并发:同一时刻,多个任务交替进行。单核CPU实现的多任务就是并发。

7、并行:同一时刻,多个任务同时进行。多核CPU可以实现并行,当任务较多时,并发和并行有可能同时发生。

二、线程基本使用

创建线程有两种方法:

1、继承Thread类,重写run方法。

2、实现Runnable接口,重写run方法。

注意:Thread类实现了Runnable接口。

(一) 继承Thread类,重写run方法

public class Thread01 {
    public static void main(String[] args) throws InterruptedException {
        Cat cat = new Cat();
        cat.start();
        System.out.println("主线程" + Thread.currentThread().getName());
        for (int i = 1; i <p>1、在继承<code>Thread</code>类,重写了<code>run()</code>方法后,在<code>main</code>方法中需要创建对象,并调用<code>start()</code>方法,启动线程。</p><p>2、使用<code>start()</code>方法,会调用重写的<code>run()</code>方法。</p><p>3、如果<code>main</code>方法中,<code>start()</code>方法后面还有执行语句,并且<code>run()</code>方法中也有执行语句,<code>main</code>线程中会启动一个子线程<code>Thread-0</code>,主线程不会阻塞,主线程与子线程会交替执行。</p><p>注意:如果主线程执行完毕,但子线程未执行完,进程不会结束,所有线程执行完毕后,进程自动结束。</p><p>4、在主线程中为什么使用<code>start()</code>方法去调用<code>run()</code>方法,而不是直接调用<code>run()</code>方法,因为<code>run()</code>方法是一个普通方法,没有真正启动线程,如果调用<code>run()</code>方法,就会将<code>run()</code>方法执行完毕后,再执行<code>main</code>方法剩余语句,主线程就会阻塞。</p><p>所以上面程序都运算结果是:</p><pre class="brush:php;toolbar:false">主线程main
主线程i=1你好1Thread-0主线程i=2你好2Thread-0主线程i=3你好3Thread-0主线程i=4你好4Thread-0主线程i=5你好5Thread-0

(二) 实现Runnable接口,重写run方法

public class Thread02 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Thread thread = new Thread(dog);
        thread.start();
    }}class Dog implements Runnable{
    @Override    public void run() {
        int count = 0;
        while (true) {
            System.out.println("小狗汪汪叫" + (++count) + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (count == 10){
                break;
            }
        }
    }}

1、因为Runnable接口中没有start()方法,所以需要代理

2、先在main方法中需要创建对象,然后创建一个Thread对象,将之前创建的对象传入Thread,借助Thread,调用start()方法,创建线程。

3、建议使用Runnable,因为实现Runnable接口更加适合多个线程共享一个资源的情况,避免了单继承的限制。

三、线程终止

(一)基本说明

1、当线程执行完任务时会自动退出。

2、也可以使用变量控制run()方法退出终止线程。

(二)操作

1、如果一个线程中的run()方法内部是一个while(true){},即一个无限循环

2、我们可以在线程内部,创建一个boolean属性loop,让loop = true,然后while(loop){}

3、再提供一个setLoop

2.

Prozess: Bezieht sich auf ein laufendes Programm. Wenn wir beispielsweise QQ verwenden, starten wir einen Prozess und das Betriebssystem weist dem Prozess Speicherplatz zu. Wenn wir Thunder verwenden und einen anderen Prozess starten, weist das Betriebssystem neuen Speicherplatz für Thunder zu.

Ein Prozess ist die Ausführung eines Programms oder eines laufenden Programms. Es handelt sich um einen dynamischen Prozess: Er hat seinen eigenen Prozess der Entstehung, Existenz und des Untergangs.

3. Thread

: Es wird vom Prozess erstellt und ist die Einheit des Prozesses. Ein Prozess kann mehrere Threads haben. Die Verwendung von Thunder zum Herunterladen von Dateien entspricht dem Prozess, und die heruntergeladene Datei entspricht dem Thread.

4. Einzelner Thread

: Gleichzeitig darf nur ein Thread ausgeführt werden.

5. Multi-Threading

: kann mehrere Threads gleichzeitig ausführen. Beispiel: Mit Thunder können Sie mehrere Dateien gleichzeitig herunterladen. 🎜🎜6. 🎜Parallelität🎜: Gleichzeitig werden mehrere Aufgaben abwechselnd ausgeführt. Multitasking, das durch eine Single-Core-CPU erreicht wird, ist Parallelität. 🎜🎜7, 🎜Parallel🎜: Gleichzeitig werden mehrere Aufgaben gleichzeitig ausgeführt. Multi-Core-CPUs können Parallelität erreichen. Bei vielen Aufgaben können Parallelität und Parallelität gleichzeitig auftreten. 🎜🎜🎜2. Grundlegende Verwendung von Threads 🎜🎜Es gibt zwei Möglichkeiten, einen Thread zu erstellen: 🎜🎜1. Erben Sie die Klasse Thread und überschreiben Sie run-Methode. 🎜🎜2. Implementieren Sie die Schnittstelle <code>Runnable und überschreiben Sie die Methode run. 🎜🎜Hinweis: Die Klasse Thread implementiert die Schnittstelle Runnable. 🎜🎜🎜(1) Erben Sie die Thread-Klasse und überschreiben Sie die Ausführungsmethode🎜
public class ThreadExit {
    public static void main(String[] args) throws InterruptedException {
        T t = new T();
        t.start();
        Thread.sleep(10000);
        t.setLoop(false);
    }}class T extends Thread{
    private boolean loop = true;
    private int times = 0;
    
    @Override    public void run() {
        while (loop){
            System.out.println("hello" + (++times));
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void setLoop(boolean loop) {
        this.loop = loop;
    }}
🎜1 Erben Sie die Thread-Klasse und schreiben Sie die run() neu. Nach der Methode code> müssen Sie ein Objekt in der Methode <code>main erstellen und die Methode start() aufrufen, um den Thread zu starten. 🎜🎜2. Durch die Verwendung der Methode start() wird die überschriebene Methode run() aufgerufen. 🎜🎜3. Wenn es in der Methode main Ausführungsanweisungen nach der Methode start() gibt, gibt es auch Ausführungsanweisungen in der Methode run()-Methode: Ein Sub-Thread <code>Thread-0 wird im Haupt-Thread gestartet. Der Haupt-Thread wird nicht blockiert, und der Haupt-Thread und der Sub-Thread werden nicht blockiert wird abwechselnd ausgeführt. 🎜🎜Hinweis: Wenn der Hauptthread die Ausführung abschließt, die Unterthreads jedoch noch nicht, wird der Prozess nicht beendet. Nachdem alle Threads die Ausführung abgeschlossen haben, wird der Prozess automatisch beendet. 🎜🎜4. Warum die Methode start() verwenden, um die Methode run() im Hauptthread aufzurufen, anstatt die Methode run() direkt aufzurufen? > Methode? , da die Methode run() eine gewöhnliche Methode ist und den Thread nicht tatsächlich startet () Nachdem die Methode ausgeführt wurde und die verbleibenden Anweisungen der main-Methode ausgeführt werden, wird der Hauptthread blockiert. 🎜🎜Das Ergebnis des obigen Programms ist also: 🎜
public class ThreadMethod01 {
    public static void main(String[] args) throws InterruptedException {
        T t = new T();
        t.setName("邱崇源");
        t.setPriority(1);
        t.start();
        for (int i = 0; i 🎜<a id="_Runnablerun_66">🎜(2) Implementieren Sie die Runnable-Schnittstelle und schreiben Sie die Ausführungsmethode neu🎜<pre class="brush:php;toolbar:false">public class ThreadMethod02 {
    public static void main(String[] args) throws InterruptedException {
        A a = new A();
        a.start();
        for (int i = 1; i 🎜1, weil es so etwas im <code nicht gibt>Ausführbare</code>-Schnittstellen-<code>start()</code>-Methode, daher ist <code>agent</code> erforderlich. 🎜🎜2. Erstellen Sie zunächst ein Objekt in der Hauptmethode, erstellen Sie dann ein <code>Thread</code>-Objekt, übergeben Sie das zuvor erstellte Objekt <code> an Thread</code> und rufen Sie <code> mit Thread auf start()</code>-Methode zum Erstellen eines Threads. 🎜🎜3. Es wird empfohlen, <code>Runnable</code> zu verwenden, da die Implementierung der Runnable-Schnittstelle besser für die gemeinsame Nutzung einer Ressource durch mehrere Threads geeignet ist und die Einschränkungen einer einzelnen Vererbung vermieden werden. 🎜🎜<a id="_97">🎜3. Thread-Beendigung 🎜🎜</a><a id="_98">🎜(1) Grundlegende Anweisungen🎜🎜1. Wenn der Thread die Aufgabe abschließt, wird er automatisch beendet. 🎜🎜2. Sie können auch Variablen verwenden, um die Methode <code>run()</code> zu steuern, um den beendeten Thread zu verlassen. 🎜🎜</a><a id="_101">🎜(2) Operation🎜🎜1. Wenn die <code>run()</code>-Methode in einem Thread intern ein <code>while(true){}</code>ist >, also eine <code>Endlosschleife</code>. 🎜🎜2. Wir können eine <code>boolesche Attributschleife</code> innerhalb des Threads erstellen, loop = true und dann <code>while(loop){}</code>. 🎜🎜3. Stellen Sie eine weitere <code>setLoop</code>-Methode bereit, damit Sie die setLoop-Methode in anderen Klassen aufrufen und den booleschen Wert ändern können, um die Thread-Beendigung zu steuern. (3) Code-Demonstration 🎜<p>2、<strong>getName</strong>:返回该线程名称。</p>
<p>3、<strong>start</strong>:使该线程开始执行,JAVA虚拟机底层调用该线程的start0方法。</p>
<p>4、<strong>run</strong>:调用线程对象的run方法。</p>
<p>5、<strong>setPriority</strong>:更改线程的优先级。</p>
<p>6、<strong>getPriority</strong>:获取线程的优先级。</p>
<p>7、<strong>sleep</strong>:在指定的毫秒数内,让当前正在执行的线程休眠。</p>
<p>8、<strong>interrupt</strong>:中断线程。</p>
<h4>
<a id="_147"></a>注意事项:</h4>
<p>1、<code>start()</code>底层会创建新的线程,调用run(),<code>run()</code>就是一个简单的方法调用,<code>不会启动新线程</code>。</p>
<p>2、<code>中断线程一般用于中断正在休眠的线程</code>,并没有真正的结束线程,所以如果线程中每输出内容后,会调用<code>Thread.sleep()</code>进行休眠的话,我们可以调用<code>interrupt()</code>方法将其<code>提前唤醒</code>。</p>
<h4>
<a id="_150"></a>代码演示:</h4>
<pre class="brush:php;toolbar:false">public class ThreadMethod01 {
    public static void main(String[] args) throws InterruptedException {
        T t = new T();
        t.setName("邱崇源");
        t.setPriority(1);
        t.start();
        for (int i = 0; i <h4>
<a id="_183"></a>(二)第二组</h4><p>1、<strong>yield</strong>:是一个<code>静态方法</code>,表示<code>线程的礼让</code>。让出<code>CPU</code>,让其他线程执行,但是<code>不一定成功</code>,因为这取决于CPU,如果CPU认为两个线程可以一起执行,则不进行礼让,所以<code>如果CPU的核数多,并且线程数少,礼让就会大概率失败</code>。</p><p>2、<strong>join</strong>:表示<code>线程的插队</code>,假如主线程与子线程正在交替运行,我们想<code>先让子线程执行</code>完毕,然后再让主线程执行,就可以使用线程插队,在主线程中,创建子线程对象,并调用<code>join</code>方法,可以实现线程插队,线程插队<code>一定会成功</code>,先<code>执行完插入线程任务后,再继续执行主线程</code>。</p><h4>
<a id="_186"></a>代码演示:</h4><pre class="brush:php;toolbar:false">public class ThreadMethod02 {
    public static void main(String[] args) throws InterruptedException {
        A a = new A();
        a.start();
        for (int i = 1; i <h2>
<a id="_219"></a>五、用户线程和守护线程</h2><p>1、<strong>用户线程</strong>:也叫<code>工作线程</code>,线程的任务执行完或通知方式结束。</p><p>2、<strong>守护线程</strong>:一般是<code>为工作线程服务</code>的,当<code>所有的用户线程结束</code>,<code>守护线程自动结束</code>。</p><h4>
<a id="_222"></a>应用场景:</h4><p>如果有两个线程,主线程运行结束,但子线程是无限循环。我们想让主线程结束的同时,子线程也结束,就需要让子线程变成守护线程。</p><p>在主线程中,创建子线程对象,并调用<code>setDaemon(true)</code>,让子线程变成守护线程。</p><p>注意:一定要放在<code>start方法之前</code>。</p><h4>
<a id="_226"></a>代码演示:</h4><pre class="brush:php;toolbar:false">public class ThreadMethod03 {
    public static void main(String[] args) throws InterruptedException {
        MyDaemonThread myDaemonThread = new MyDaemonThread();
        myDaemonThread.setDaemon(true);
        myDaemonThread.start();
        for (int i = 1; i <h2>
<a id="_254"></a>六、线程的生命周期</h2><h4>
<a id="1JDK__ThreadState__255"></a>1、JDK 中用 Thread.State 枚举表示了线程的几种状态</h4><p><img src="https://img.php.cn/upload/article/000/000/067/2235493b090cc60a6a3c1434c8852f59-0.png" alt="Zusammenfassung der Java-Wissenspunkte: Multithreading-Grundlagen"></p><h4>
<a id="2_257"></a>2、线程状态转换图</h4><p><img src="https://img.php.cn/upload/article/000/000/067/cfbba58b413c41b084c9e0cab6295dfe-1.png" alt="Zusammenfassung der Java-Wissenspunkte: Multithreading-Grundlagen"></p><h2>
<a id="_259"></a>七、线程的同步</h2><h4>
<a id="1_260"></a>1、应用场景:</h4><p>假如有100张票,有三个线程同时进入该方法买票,票就有可能超卖。所以我们需要线程同步机制,保证数据在同一时刻,最多有一个线程访问。</p><p>可以采取同步方法,在方法中加入<code>synchronized</code>关键字。</p><p>也可以采用同步代码块,<code>synchronized(对象){}</code>。</p><p>注意:<code>synchronized是非公平锁</code>,如果这次第一个线程访问了数据,那么下一次第一个线程也有可能访问到数据。</p><p>如果同步方法是<code>非静态</code>的,那么锁可以是this,也可以是其他对象,但要求是同一个对象。</p><p>例:<code>synchronized(this)</code>。</p><p>如果同步方法是<code>静态</code>的,锁为当前类本身。</p><p>例:<code>synchronized(类名:class)</code>。</p><h4>
<a id="2_270"></a>2、代码演示:</h4><pre class="brush:php;toolbar:false">public class SellTicket {
    public static void main(String[] args) {
        SellTicket02 sellTicket04 = new SellTicket02();
        Thread thread1 = new Thread(sellTicket04);
        Thread thread2 = new Thread(sellTicket04);
        Thread thread3 = new Thread(sellTicket04);
        thread1.start();
        thread2.start();
        thread3.start();
    }}class SellTicket02 implements Runnable {
    public static int ticket = 100;
    private boolean loop = true;

    public synchronized void sell() {
        if (ticket <h2>
<a id="_309"></a>八、线程的死锁</h2><h4>
<a id="1_310"></a>1、基本介绍</h4><p>多个线程都占用了对方的锁资源,但不肯相让,就导致了死锁,在编程中,一定要避免死锁的发生。</p><h4>
<a id="2_312"></a>2、发生场景:</h4><p>例如:A和B的面前都各有两道门,A的第一道门是o1,第二道门是o2。B的第一道门是o2,第二道门是o1。他们的面前有两把锁,一个是o1锁,一个是o2锁,假如A抢到了o1锁,B抢到了o2锁,但是他们只可打开各自的第一道门,第二道门都没有打开,那么他们都无法释放自己的锁资源,又不可能相让,因此发生了死锁。</p><h4>
<a id="3_314"></a>3、代码演示:</h4><pre class="brush:php;toolbar:false">public class DeadLock_ {
	public static void main(String[] args) { //模拟死锁现象 
		DeadLockDemo A = new DeadLockDemo(true); 
		A.setName("A 线程"); 
		DeadLockDemo B = new DeadLockDemo(false); 
		B.setName("B 线程");
		A.start(); 
		B.start(); 
	} }class DeadLockDemo extends Thread { 
	static Object o1 = new Object();// 保证多线程,共享一个对象,这里使用 static 
	static Object o2 = new Object(); 
	boolean flag; 
	
	public DeadLockDemo(boolean flag) {//构造器 
		this.flag = flag; 
	}
	
	@Override 
	public void run() {  
		if (flag) { 
			synchronized (o1) { 
				System.out.println(Thread.currentThread().getName() + " 进入 1"); 
				synchronized (o2) { 
					System.out.println(Thread.currentThread().getName() + " 进入 2"); 
				} 
			} 
		} else {
			synchronized (o2) { 
				System.out.println(Thread.currentThread().getName() + " 进入 3"); 
				synchronized (o1) {  
					System.out.println(Thread.currentThread().getName() + " 进入 4"); 
				} 
			} 
		} 
	} }

九、释放锁

1、下面操作会释放锁

当前线程的同步方法,同步代码块执行结束。
当前线程在同步代码块,同步方法中遇到break,return
当前线程在同步代码块,同步方法中出现了未处理的错误或异常,导致异常结束。
当前线程在同步代码块,同步方法中执行的线程对象的wait方法,当前线程暂停,并释放锁。

2、 下面操作不会释放锁

线程执行同步代码块和同步方法时,程序调用Thread.sleep(),Thread.yield()方法暂停当前线程的执行,不会释放锁。
线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁。

推荐学习:《java视频教程

Das obige ist der detaillierte Inhalt vonZusammenfassung der Java-Wissenspunkte: Multithreading-Grundlagen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen