1. 程式人生 > 實用技巧 >一篇文章帶你瞭解HTML格式化元素

一篇文章帶你瞭解HTML格式化元素

1. 執行緒的三種建立方式

1.1 Callable 介面實現

public class CallableDemo implements Callable {
    @Override
    public Object call() throws Exception {
        return null;
    }
    @Override
    public void run() {
        System.out.println("runnable 實現的執行緒");
    }
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        Callable callable = new CallableDemo();
        Future<String> t1 = executor.submit(callable);
        String s = t1.get();
        System.out.println("開始消費");
    }
}

1.2 繼承Thread 介面

public class Threaddemo extends Thread {
    @Override
    public void run() {
        System.out.println("hello");
    }

    public static void main(String[] args) {
        new Threaddemo().start();
    }
}

1.3 實現runnable 介面

public class CallableDemo implements Runnable {
    @Override
    public void run() {
        System.out.println("runnable 實現的執行緒");
    }
    public static void main(String[] args) {
        Thread thread = new Thread(new CallableDemo());
        thread.start();
    }
}

2. 執行緒的生命週期

3. 執行緒的基本操作

jion 阻塞主執行緒例項

public class Demo3  implements  Runnable{
    static int num;
    @Override
    public void run() {
        for (int i = 0; i < 20000; i++) {
            num++;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new Demo3());
            thread.start();
//            thread.join(); //阻塞主執行緒,執行緒卓個執行 //阻塞主執行緒,卓個建立子執行緒執行,減少併發
        }
        Thread.sleep(2000);
        System.out.println(num);

    }
}
1. join 阻塞的是主執行緒
2. 因為多執行緒的執行是非同步的,如果寫程式碼時候,如果不阻塞主執行緒,有時候資料操作的值輸出並不完整

wait notify 例項

main

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Queue<Integer> queue = new LinkedList<>();
        new Thread(new Puroduce(queue,100)).start();
        new Thread(new Consumer(queue,100)).start();

        Thread.sleep(1000);

        // 生產者一直生產, 直到到達100個,停止生產,阻塞 ---》 通知消費者消費
        // 消費者一直消費,沒有可以消費的, 就停止消費, 阻塞;---》 通知生產者生產

    }
}

生產者

public class Puroduce implements Runnable {
    Queue<Integer> queue;
    private int size;

    public Puroduce(Queue<Integer> queue, int size) {
        this.queue = queue;
        this.size = size;
    }

    private void produce() throws Exception {
        int i = 0;
        while (true) {
            i++;
            synchronized (queue) {
                while (queue.size() == size) {
                    System.out.println("已經滿了");
                    queue.wait();
                }
                queue.add(i);
                System.out.println("生產者開始生產: " + i);
                Thread.sleep(100);
                queue.notifyAll();
            }
        }
    }
    @Override
    public void run() {
        try {
            produce();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

消費者

public class Consumer implements Runnable {
    Queue<Integer> queue;
    private int size = 0;
    public Consumer(Queue<Integer> queue, int size) {
        this.queue = queue;
        this.size = size;
    }
    private void sonsume() throws Exception {
        int i = 0;
        synchronized (queue) {
            while (true) {
                i++;
                while (queue.isEmpty()){
                    System.out.println("已經消費完了");
                    queue.wait();
                }
                Integer remove = queue.remove();
                System.out.println("消費者開始消費: " + remove);
                Thread.sleep(100);
                queue.notifyAll();
            }
        }
    }
    @Override
    public void run() {
        try {
            sonsume();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

總結

synchronized 物件鎖 鎖住同樣一個物件 讓兩個執行緒相互通訊

sleep

interrupter

4. 執行緒安全問題

使用多執行緒帶來的麻煩 原子性 可見性 有序性

4. 1 原子性 例項

public class Demo extends Thread {
    private static int num=100000;
    @Override
    public void run() {
        addNumber();
    }
// 如果不加synchronized 由於cpu的時間片的切換,有的減法操作丟失了他的執行權力,再次執行時資料產生偏差
   [synchronized]  static public void addNumber() {
        for (int i1 = 0; i1 < 5000; i1++) {
            num--;
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[20];
        for (int i = 0; i < threads.length; i++) {
            new Thread(new Demo()).start();
        }
        System.out.println( "結果:" + num);
    }
}

4. 2 可見性 例項

public class Demo  {
// volatile 使flag 可以被其他執行緒可見
    static volatile boolean flag =true;
    public static void main(String[] args) throws InterruptedException {
        new Thread(()->{
                    int i =0;
                    while (flag) {
                        i++;
                    }
                }
        ).start();
        Thread.sleep(1000); //主執行緒不成睡,會直接執行結束,不會顯示答案
        flag=false;
    }

4. 3 有序性 例項

CPU 的編譯,指令優化會破壞語句的執行順序

5. 解決的方法

5. 1 synchronized 物件鎖用法

  1. 同步方法

  2. 同步靜態方法

    synchronized static (this) {//物件
    }
    
  3. 同步方法塊

    synchronized (this) {
    }
    

5.2 synchronized 物件鎖例項

public class Demo3  implements  Runnable{
    static int num;
    synchronized static void add() { // 若果不是靜態的方法,每一個物件一個方法,就不是爭用資源,鎖不住。
        for (int i = 0; i < 20000; i++) {
            num++;
        }
    }
    @Override
    public void run() {
        add();
    }
    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new Demo3());
            thread.start();
        }
        Thread.sleep(2000);
        System.out.println(num);

    }
}

6. JUC 包和AQS

重入鎖ReentrantLock

public class Demo3  implements  Runnable{
    static int num;
    static ReentrantLock lock = new ReentrantLock(); // 可以鎖住非非靜態方法

    void add() {
        lock.lock();
        for (int i = 0; i < 20000; i++) {
            num++;
        }
        lock.unlock();
    }

    @Override
    public void run() {
        add();
    }

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new Demo3());
            thread.start();
        }
        Thread.sleep(2000);
        System.out.println(num);

    }
}
重入鎖的意思,就是一個物件在訪問多個爭用資源時候,拿到了相同的鎖之後,就不用再去獲得鎖

如果是共享鎖,物件在訪問多個爭用資源的時候,獲得了一個鎖,別的物件沒有鎖不能訪問該資源,而訪問第二個爭用資源時,又沒有先釋放鎖,造成了死鎖現象。

7. java 中如何使用執行緒池

7.1執行緒池的類別

7.1執行緒池的使用方法 Executors.newFixedThreadPool 例項

public class Demo4 implements  Runnable{
    static int num;
    synchronized static void add() {
        for (int i = 0; i < 20000; i++) {
            num++;
        }
    }
    @Override
    public void run() {
        add();
        System.out.println(Thread.currentThread().getName());
    }

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 3; i++) {//啟動3個任務
            executorService.execute(new Demo4());
        }
        Thread.sleep(200);
        System.out.println("最終結果: "+ num);
        executorService.shutdownNow();
    }
}