1. 程式人生 > 實用技巧 >多執行緒學習筆記(狂神說視訊21-28)

多執行緒學習筆記(狂神說視訊21-28)

CopyOnWriteArrayList

public class TestJUC {
    public static void main(String[] args) throws InterruptedException {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
        for (int i = 0; i < 1000; i++) {
            new Thread(()-> {
                list.add(Thread.currentThread().getName());
            }).start();
        }
        Thread.sleep(3000);
        System.out.println(list.size());
    }
}

死鎖

死鎖:多個執行緒互相抱著對方需要的資源,然後形成僵持

public class DeadLock {
    public static void main(String[] args) {
        Makeup g1 = new Makeup(1,"灰姑娘");
        Makeup g2 = new Makeup(1,"白雪公主");
        g1.start();
        g2.start();
    }

}

//口紅
class Lipstick{

}

//鏡子
class Mirror{

}

class Makeup extends Thread{
    //需要的資源只有一份,所以要用static
    static Lipstick l = new Lipstick();
    static Mirror m = new Mirror();

    int choice;//選擇
    String girlName;//選擇化妝品的人
    Makeup(int choice,String girlName){
        this.choice = choice;
        this.girlName = girlName;
    }

    @Override
    public void run() {
        //化妝
        try {
            makeup();
        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    //化妝,互相持有對方的鎖,就是需要拿到對方的資源
    private void makeup() throws InterruptedException {
        if (choice == 0) {
            synchronized (l)//獲得口紅的鎖
            {
                System.out.println(this.girlName + "獲得了口紅的鎖");
                Thread.sleep(1000);
            }
            synchronized (m)//一秒鐘後想獲得鏡子的鎖
            {
                System.out.println(this.girlName + "獲得鏡子的鎖");
            }
        } else {
            synchronized (m)//獲得鏡子的鎖
            {
                System.out.println(this.girlName + "獲得了鏡子的鎖");
                Thread.sleep(2000);
            }
            synchronized (l)//一秒鐘後想獲得口紅的鎖
            {
                System.out.println(this.girlName + "獲得口紅的鎖");
            }
        }
    }
}

執行結果

Lock鎖

import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
    public static void main(String[] args) {
        TestLock2 testLock2 = new TestLock2();
        new Thread(testLock2).start();
        new Thread(testLock2).start();
        new Thread(testLock2).start();
    }

}

class TestLock2 implements Runnable{

    int ticketNums = 10;

    //定義Lock鎖
    private final ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true){
            try{
                lock.lock();//加鎖
                if (ticketNums >0){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"==>"+ticketNums--);
                }else {
                    break;
                }
            }finally {
                lock.unlock();//解鎖
            }
        }
    }
}

執行結果

生產者消費者問題

管程法

//測試:生產者消費者模型-》利用緩衝區解決:管程法
//生產者,消費者,長跑,緩衝區
public class TestPC {

    public static void main(String[] args) {
        SynContainer c = new SynContainer();
        new Productor(c).start();
        new Consumer(c).start();

    }

}
//生產者
class Productor extends Thread{
    SynContainer container;
    public Productor(SynContainer container) {
        this.container = container;
    }

    //生產
    @Override
    public void run() {
        for(int i=0;i<100;i++)
        {
            container.push(new Chicken(i));
            System.out.println("生產了第"+i+"只雞");
        }
    }
}
//消費者
class Consumer extends Thread{
    SynContainer container;
    public Consumer(SynContainer container) {
        this.container = container;
    }

    //消費
    @Override
    public void run() {
        for(int i=0;i<100;i++)
        {
            System.out.println("消費了第"+container.pop().id+"只雞");
        }
    }
}
//產品
class Chicken{
    int id;//編號
    public Chicken(int id)
    {
        this.id = id;
    }
}
//緩衝區
class SynContainer{
    //容器大小
    Chicken[] chickens = new Chicken[10];
    //容器計數器
    int count = 0;

    //生產者放入產品
    public synchronized void push(Chicken chicken)
    {
        //如果容器滿了,就需要等待消費者消費
        if(count == chickens.length)
        {
            //通知消費者消費,生產等待
            try {
                this.wait();
            }catch(Exception e) {
                e.printStackTrace();
            }
        }
        //如果沒有滿,我們就需要丟入產品
        chickens[count] = chicken;
        count++;
        //可以通知消費者了
        this.notifyAll();
    }
    //消費者消費產品

    //消費者消費產品
    public synchronized Chicken pop() {
        //判斷能否消費
        if(count==0)
        {
            //等待生產者生產,消費者等待
            try {
                this.wait();
            }catch(Exception e)
            {
                e.printStackTrace();
            }
        }

        //如果可以消費
        count--;
        Chicken chicken = chickens[count];
        //吃完了,通知生產者生產
        this.notifyAll();
        return chicken;
    }
}

執行結果

訊號燈法

//測試生產消費者問題2,訊號燈法,標誌位解決
public class TestPC2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TV tv = new TV();
        new player(tv).start();
        new Watcher(tv).start();
    }

}
//生產者-》演員
class player extends Thread{
    TV tv;
    public player(TV tv)
    {
        this.tv = tv;
    }
    @Override
    public void run() {
        for(int i=0;i<20;i++)
        {
            if(i%2==0)
            {
                this.tv.play("綜藝節目");
            }
            else
            {
                this.tv.play("小視訊");
            }
        }
    }
}
//消費者-》觀眾
class Watcher extends Thread{
    TV tv;
    public Watcher(TV tv)
    {
        this.tv = tv;
    }
    @Override
    public void run() {
        for(int i=0;i<20;i++)
        {
            tv.watch();
        }
    }
}
//產品-》節目
class TV {
    //演員錄製,觀眾等待
    //觀眾觀看,演員等待
    String voice;//表演的節目
    boolean flag = true;

    //錄製
    public synchronized void play(String voice) {
        if(!flag)
        {
            try {
                this.wait();
            }catch(Exception e)
            {
                e.printStackTrace();
            }
        }
        System.out.println("演員錄製了"+voice);
        //通知觀眾觀看
        this.notifyAll();
        this.voice = voice;
        this.flag = !this.flag;
    }
    //觀眾看
    public synchronized void watch() {
        if(flag)
        {
            try {
                this.wait();
            }catch(Exception e)
            {
                e.printStackTrace();
            }
        }
        System.out.println("觀看了"+voice);
        //通知演員錄製
        this.notifyAll();
        this.flag = !this.flag;
    }
}

執行結果

執行緒池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//測試執行緒池
public class TestPool {

    public static void main(String[] args) {

        //1.建立執行緒池
        ExecutorService service = Executors.newFixedThreadPool(10);
        //執行
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        //關閉連線
        service.shutdown();
    }

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

執行結果

總結

//回顧總結執行緒的建立
public class ThreadNew {

    public static void main(String[] args) {

        new MyThread1().start();
        new Thread(new MyThread2()).start();

        FutureTask<Integer> f = new FutureTask<Integer>(new MyThread3());
        new Thread(f).start();
        try {
            Integer i = f.get();
            System.out.println(i);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

//1.繼承Thread類
class MyThread1 extends Thread {
    @Override
    public void run() {
        System.out.println("MyThread1");
    }
}

//2.實現Runnable介面
class MyThread2 implements Runnable {
    @Override
    public void run() {
        System.out.println("MyThread2");
    }
}

//3.實現Callable介面
class MyThread3 implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        System.out.println("MyThread3");
        return 100;
    }
}

執行結果