Rumah  >  Artikel  >  Java  >  Ringkasan mata pengetahuan Java: asas berbilang benang

Ringkasan mata pengetahuan Java: asas berbilang benang

WBOY
WBOYke hadapan
2022-11-15 17:24:221828semak imbas

Artikel ini membawakan anda pengetahuan yang berkaitan tentang java, yang terutamanya memperkenalkan kandungan yang berkaitan tentang berbilang benang boleh dilaksanakan pada masa yang sama. Contohnya: Anda boleh menggunakan Thunder untuk memuat turun berbilang fail pada masa yang sama. Mari kita lihat.

Ringkasan mata pengetahuan Java: asas berbilang benang

Pembelajaran yang disyorkan: "tutorial video java"

Konsep berkaitan benang

1. Program: Ia adalah satu set arahan yang ditulis dalam bahasa tertentu untuk menyelesaikan tugas tertentu. Ringkasnya: 就是我们写的代码.

2. Proses: merujuk kepada program yang sedang berjalan Contohnya, apabila kita menggunakan QQ, kita memulakan proses dan sistem pengendalian akan memperuntukkan ruang memori untuk proses tersebut. Apabila kami menggunakan Thunder dan memulakan proses lain, sistem pengendalian akan memperuntukkan ruang memori baharu untuk Thunder.

Proses ialah pelaksanaan program, atau program yang sedang berjalan. Ia adalah proses yang dinamik: ia mempunyai proses kemunculan, kewujudan dan kematiannya sendiri.

3. Thread : Ia dicipta oleh proses dan merupakan entiti proses, 一个进程可以有多个线程 Contohnya, jika anda menggunakan Thunder untuk memuat turun fail, Thunder adalah bersamaan dengan proses, dan fail yang dimuat turun adalah bersamaan dengan benang.

4. Urut tunggal: Pada masa yang sama, 只允许执行一个线程.

5. Berbilang benang: Pada masa yang sama, 可以执行多个线程. Contohnya: menggunakan Thunder anda boleh memuat turun berbilang fail pada masa yang sama.

6 Konkurensi: Pada masa yang sama, 多个任务交替进行. Berbilang tugas yang dicapai oleh CPU teras tunggal adalah serentak.

7. Sejajar : Pada masa yang sama, 多个任务同时进行. CPU berbilang teras boleh mencapai keselarian Apabila terdapat banyak tugas, keselarasan dan keselarian mungkin berlaku pada masa yang sama.

2. Penggunaan asas urutan

Terdapat dua cara untuk mencipta urutan:

1 Warisi kelas Thread dan ganti run kaedah .

2. Laksanakan antara muka Runnable dan ganti kaedah run.

Nota: Kelas Thread melaksanakan antara muka Runnable.

(1) Warisi kelas Thread dan ganti kaedah 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 Selepas mewarisi kelas <code>Thread</code> dan mengatasi kaedah <code>run()</code>, Dalam kaedah <code>main</code>, anda perlu mencipta objek dan memanggil kaedah <code>start()</code> untuk memulakan urutan. </p><p>2. Menggunakan kaedah <code>start()</code> akan memanggil kaedah <code>run()</code> yang ditindih. </p><p>3 Jika dalam kaedah <code>main</code>, terdapat pernyataan pelaksanaan selepas kaedah <code>start()</code>, dan terdapat juga pernyataan pelaksanaan dalam kaedah <code>run()</code>, sub-utas <code>main</code> akan dimulakan dalam utas <code>Thread-0</code>, dan utas utas tidak akan disekat, dan utas utama dan utas anak akan dilaksanakan secara bergilir-gilir. </p><p>Nota: Jika utas utama menyelesaikan pelaksanaan tetapi sub-utas belum menyelesaikan pelaksanaan, proses itu tidak akan tamat Selepas semua utas selesai melaksanakan, proses akan tamat secara automatik. </p><p>4 Mengapa menggunakan kaedah <code>start()</code> untuk memanggil kaedah <code>run()</code> dalam utas utama dan bukannya memanggil kaedah <code>run()</code> secara langsung, kerana kaedah <code>run()</code> adalah kaedah biasa dan sebenarnya tidak mulakan utas. Jika Memanggil kaedah <code>run()</code> akan melengkapkan pelaksanaan kaedah <code>run()</code> dan kemudian laksanakan penyataan baki kaedah <code>main</code>, dan utas utama akan disekat. </p><p>Jadi hasil program di atas ialah: </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

(2) Laksanakan antara muka Runnable dan tulis semula kaedah 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 , kerana tiada kaedah Runnable dalam antara muka start(), jadi 代理 diperlukan.

2. Mula-mula, anda perlu mencipta objek dalam kaedah utama, dan kemudian mencipta objek Thread Gunakan objek 传入Thread yang telah dibuat sebelum ini dan gunakan Thread untuk memanggil kaedah start() untuk mencipta seutas benang.

3. Adalah disyorkan untuk menggunakan Runnable, kerana melaksanakan antara muka Runnable adalah lebih sesuai untuk berbilang urutan untuk berkongsi sumber dan mengelakkan pengehadan warisan tunggal.

3. Penamatan benang

(1) Arahan asas

1 tugasan.

2. Anda juga boleh menggunakan kaedah kawalan pembolehubah run() untuk keluar dari urutan penamatan.

(2) Operasi

1. Jika kaedah run() dalam benang secara dalaman ialah while(true){}, iaitu 无限循环.

2. Kita boleh mencipta boolean属性loop di dalam benang, biarkan gelung = benar, dan kemudian while(loop){}.

3. Sediakan kaedah setLoop yang lain supaya anda boleh memanggil kaedah setLoop dalam kelas lain dan menukar nilai boolean untuk mengawal penamatan benang. ( 1) Kumpulan pertama

1 setName: Tetapkan nama utas supaya sama dengan nama parameter.

2、getName:返回该线程名称。

3、start:使该线程开始执行,JAVA虚拟机底层调用该线程的start0方法。

4、run:调用线程对象的run方法。

5、setPriority:更改线程的优先级。

6、getPriority:获取线程的优先级。

7、sleep:在指定的毫秒数内,让当前正在执行的线程休眠。

8、interrupt:中断线程。

注意事项:

1、start()底层会创建新的线程,调用run(),run()就是一个简单的方法调用,不会启动新线程

2、中断线程一般用于中断正在休眠的线程,并没有真正的结束线程,所以如果线程中每输出内容后,会调用Thread.sleep()进行休眠的话,我们可以调用interrupt()方法将其提前唤醒

代码演示:

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="Ringkasan mata pengetahuan Java: asas berbilang benang"></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="Ringkasan mata pengetahuan Java: asas berbilang benang"></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视频教程

Atas ialah kandungan terperinci Ringkasan mata pengetahuan Java: asas berbilang benang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:csdn.net. Jika ada pelanggaran, sila hubungi admin@php.cn Padam