JAVA.SE 多線程

1.並行與併發

並行:兩個事件在同一時刻發生
併發:兩個事件在同一時間段交替進行
在這裏插入圖片描述在這裏插入圖片描述

2.進程與線程

進程:我們在內存中運行程序,我們稱之爲進程
線程:完成某個模塊,稱之爲線程,例如迅雷下載
線程是屬於某個進程的,每個進程都至少包含一個線程
線程調度:
分時調度:每個線程平均分配cpu的使用權
搶佔式調度:隨機分配
Java中採用搶佔式調度

3Thread類

右鍵運行程序至少調用兩個線程
main方法的線程稱之爲主線程
垃圾回收器線程
成員方法:
getname獲取線程的名字
setname獲取線程的名字
run代表要執行的任務
start啓動該線程
sleep該線程休眠
currentThread獲取當前線程

3.1創建線程

3.1.1繼承

創建子類,繼承Thread
子類中重寫run方法
創建子類對象
調用start方法

package com.itcast.Text04;

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(currentThread().getName()+i);
        }

    }
}

package com.itcast.Text04;

public class Demo01 {
    public static void main(String[] args) {
        MyThread m = new MyThread();
       // m.run();
        m.start();
        for (int i = 0; i < 100; i++) {
            System.out.println("main"+i);
        }
    }
}


3.1.2實現方式

定義實現類
重寫run方法
調用


package com.itcast.Text04;

public class MyRunable implements Runnable {


    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("runable"+i);
        }
    }
}
package com.itcast.Text04;

public class Text03 {
    public static void main(String[] args) {
        MyRunable m = new MyRunable();

        Thread t = new Thread(m);
        t.start();
        for (int i = 0; i < 100; i++) {
            System.out.println("main" +i);
        }
    }
}



3.1.3匿名內部類形式


package com.itcast.Text04;

public class Text02 {
    public static void main(String[] args) {
        new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println(currentThread().getName() + i);
                }
            }
        }.start();
        
        for (int i = 0; i < 100; i++) {
            System.out.println("main"+i);
        }
    }
}



3.1.4兩種方式的比較

實現類方式比較好,線程和任務是分開的,由程序員自己組合
實現避免了Java單繼承的不足
實現是線程解耦合,繼承是耦合的

4.高併發與線程安全

高併發:某個時間點有大量的用戶訪問同一資源
線程安全:出現高併發後不會出現不符合實際的數據
線程安全的問題:
可見性
有序性:
原子性

5.volatile關鍵字

volatile用來修飾成員變量的靜態方法,可以解決多線程的可見性有序性問題

package com.itcast.Text05;

public class MyThread extends  Thread {
    public volatile static int a = 0;

    @Override
    public void run() {
        System.out.println("線程啓動了");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("將a的值修改");
        a = 1;
        System.out.println("線程結束");
    }
}


package com.itcast.Text05;

public class Text01 {
    public static void main(String[] args) {
        MyThread m = new MyThread();

        m.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        while (true) {
            if (MyThread.a == 1) {
                System.out.println("a的值爲1");
                return;
            }
        }
    }
}


注意:
volatile不能解決原子性問題
只能解決可見性,順序性

6.原子類

原子類:保證了數據操作的原子性,中間不會被其他線程打斷
AtomicInteger:對變量操作的原子類
getAtomicInteger相當於對原子變量的++
incrementAnGet相當於++變量


package com.itcast.Text05;

import java.util.concurrent.atomic.AtomicInteger;

public class MyThread01 extends Thread {
    public static AtomicInteger a = new AtomicInteger();

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            a.getAndIncrement();
        }
        System.out.println("修改完成");

    }
}
package com.itcast.Text05;

public class Text02 {
    public static void main(String[] args) throws InterruptedException {
        MyThread01 mm = new MyThread01();
        MyThread01 mm1 = new MyThread01();
        mm.start();
        mm1.start();
        Thread.sleep(2000);
        System.out.println(MyThread01.a);

    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章