欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java多線程學(xué)習(xí)筆記

 更新時(shí)間:2021年09月30日 15:10:01   作者:四季人06  
常用的實(shí)現(xiàn)多線程的兩種方式:Thread和Runnable。之所以說(shuō)是“常用”,是因?yàn)樵贘ava 5后可以通過(guò)java.util.concurrent包中的線程池來(lái)實(shí)現(xiàn)多線程

多任務(wù)、多線程

在多任務(wù)場(chǎng)景下,兩件事看上去同時(shí)在做,但實(shí)際上,你的大腦在同一時(shí)間只做一件事,間隔時(shí)間可能很少,但這似乎讓你感覺(jué)這兩件事是同時(shí)在做

考慮阻塞問(wèn)題,引入多線程的場(chǎng)景,多線程并發(fā)場(chǎng)景

在這里插入圖片描述

程序、進(jìn)程、線程

程序=指令+數(shù)據(jù)(靜態(tài)的)
在操作系統(tǒng)中運(yùn)行的程序就是進(jìn)程,一個(gè)進(jìn)程可以有多個(gè)線程
比如,看視頻時(shí)聽(tīng)聲音,看圖像,看彈幕等

學(xué)著看jdk文檔

比如你要看Thread
你可以搜索,然后閱讀

在這里插入圖片描述

往下翻你會(huì)看到:

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

線程的創(chuàng)建

1.繼承Thread類

//創(chuàng)建線程方式一:繼承Thread類,重寫(xiě)run方法,調(diào)用start()方法開(kāi)啟線程
public class TestThread1  extends Thread{

    @Override
    public void run() {
        //run()方法線程體
        IntStream.range(0,20).forEach(i->{
            System.out.println("我在看代碼"+i);
        });
    }

    public static void main(String[] args) {
        //創(chuàng)建一個(gè)線程對(duì)象
        TestThread1 testThread1=new TestThread1();
        //調(diào)用start()方法,啟動(dòng)線程,不一定立即執(zhí)行,由cpu調(diào)度執(zhí)行
        testThread1.start();

        //主方法 main方法
        IntStream.range(0,20).forEach(i->{
            System.out.println("我在學(xué)習(xí)多線程"+i);
        });
    }
}

一個(gè)小練習(xí):

//練習(xí)thread實(shí)現(xiàn)對(duì)線程同步下載圖片
public class TestThread2 extends Thread{

    private String url;
    private String name;

    public TestThread2(String url, String name) {
        this.url = url;
        this.name = name;
    }

    @Override
    public void run() {
          WebDownload webDownload=new WebDownload();
          webDownload.downloader(url,name);
          System.out.println("下載了文件名:"+name);
    }

    public static void main(String[] args) {
        TestThread2 t1=new TestThread2("https://profile.csdnimg.cn/B/D/2/3_sxh06","1.jpg");
        TestThread2 t2=new TestThread2("https://profile.csdnimg.cn/B/D/2/3_sxh06","2.jpg");
        TestThread2 t3=new TestThread2("https://profile.csdnimg.cn/B/D/2/3_sxh06","3.jpg");

        t1.start();
        t2.start();
        t3.start();

    }
}

//下載器
class WebDownload{
    //下載方法
    public void downloader(String url,String name)  {
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO異常,downloader方法出錯(cuò)");
        }
    }
}

2.實(shí)現(xiàn)Runable接口

//創(chuàng)建線程的方法2:實(shí)現(xiàn)Runable接口
public class TestThread3 implements Runnable{

    @Override
    public void run() {
        //run()方法線程體
        IntStream.range(0,20).forEach(i->{
            System.out.println("我在看代碼"+i);
        });
    }

    public static void main(String[] args) {
        //創(chuàng)建一個(gè)線程對(duì)象
        TestThread3 testThread3=new TestThread3();
        //調(diào)用start()方法,啟動(dòng)線程,不一定立即執(zhí)行,由cpu調(diào)度執(zhí)行
//        Thread thread=new Thread(testThread3);
//        thread.start();

        //或者這樣簡(jiǎn)寫(xiě)
       new Thread(testThread3).start();
        //主方法 main方法
        IntStream.range(0,100).forEach(i->{
            System.out.println("我在學(xué)習(xí)多線程"+i);
        });
    }
}

在這里插入圖片描述

理解并發(fā)的場(chǎng)景

當(dāng)多個(gè)線程使用同一個(gè)資源時(shí),會(huì)出現(xiàn)問(wèn)題,看看下面這個(gè)買火車票的例子:

public class TestThread4 implements  Runnable{

    //票數(shù)
    private int ticketNums=10;

    @Override
    public void run() {
        while(true){
            if (ticketNums<=0){
                break;
            }
            //模擬延遲
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"張票");
        }

    }

    public static void main(String[] args) {
        TestThread4 ticket=new TestThread4();

        new Thread(ticket,"小明").start();
        new Thread(ticket,"張三").start();
        new Thread(ticket,"李四").start();
    }
}

看看運(yùn)行的結(jié)果:

在這里插入圖片描述

可以看到案例中的線程不安全問(wèn)題,同時(shí)數(shù)據(jù)也是不正確的

龜兔賽跑場(chǎng)景

/**
 * 模擬龜兔賽跑
 */
public class Race implements Runnable{
    //勝利者
    private static String winner;

    @Override
    public void run() {


        for (int i=0;i<=100;i++){
            //模擬兔子休息
            if (Thread.currentThread().getName().equals("兔子")&&i%10==0){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            boolean flag=gameOver(i);
            if (flag){  //判斷比賽是否結(jié)束
               break;
            }
            System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步");
        }

    }

    /**
     * 判斷比賽是否結(jié)束
     */
    private boolean gameOver(int steps){
        //判斷是否有勝利者
        if (winner !=null){
            //已經(jīng)存在勝利者
            return true;
        }else if (steps >= 100){
            winner=Thread.currentThread().getName();
            System.out.println("勝利者是:"+winner);
            return true;
        }else{
            return false;
        }
    }

    public static void main(String[] args) {
        Race race=new Race();
        new Thread(race,"兔子").start();
        new Thread(race,"烏龜").start();
    }
}

實(shí)現(xiàn)callable接口

//線程創(chuàng)建方式3
public class TestCallable implements Callable<Boolean> {
    private String url;
    private String name;

    public TestCallable(String url, String name) {
        this.url = url;
        this.name = name;
    }

    @Override
    public Boolean call() {
        com.sxh.thread.WebDownload webDownload=new com.sxh.thread.WebDownload();
        webDownload.downloader(url,name);
        System.out.println("下載了文件名:"+name);
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCallable t1=new TestCallable("https://profile.csdnimg.cn/B/D/2/3_sxh06","1.jpg");
        TestCallable t2=new TestCallable("https://profile.csdnimg.cn/B/D/2/3_sxh06","2.jpg");
        TestCallable t3=new TestCallable("https://profile.csdnimg.cn/B/D/2/3_sxh06","3.jpg");

        //創(chuàng)建執(zhí)行服務(wù)
        ExecutorService ser= Executors.newFixedThreadPool(3);
        //提交執(zhí)行
        Future<Boolean> r1=ser.submit(t1);
        Future<Boolean> r2=ser.submit(t2);
        Future<Boolean> r3=ser.submit(t3);
        //獲取結(jié)果
        boolean rs1=r1.get();
        boolean rs2=r2.get();
        boolean rs3=r3.get();
        //關(guān)閉服務(wù)
        ser.shutdownNow();
    }

}

理解函數(shù)式接口

任何接口,只包含唯一一個(gè)抽象方法,就是函數(shù)式接口

/**
 * lambdab表達(dá)式的發(fā)展
 */
public class TestLambda1 {
    //3.靜態(tài)內(nèi)部類
    static class Like2 implements ILike{
        @Override
        public void lambda() {
            System.out.println("i like lambda2");
        }
    }

    public static void main(String[] args) {
        ILike like=new Like();
        like.lambda();

        like=new Like2();
        like.lambda();

        //4.局部?jī)?nèi)部類
       class Like3 implements ILike{
            @Override
            public void lambda() {
                System.out.println("i like lambda3");
            }
        }
        like=new Like3();
        like.lambda();

        //5.匿名內(nèi)部類
        like=new ILike() {
            @Override
            public void lambda() {
                System.out.println("i like lambda4");
            }
        };
        like.lambda();

        //6.用lambda簡(jiǎn)化
        like=()->{
            System.out.println("i like lambda5");
        };
        like.lambda();
    }
}

//1.定義一個(gè)函數(shù)式接口
interface ILike{
    void lambda();
}

//2.實(shí)現(xiàn)類
class Like implements ILike{

    @Override
    public void lambda() {
        System.out.println("i like lambda");
    }
}

理解線程的狀態(tài)

在這里插入圖片描述

線程停止

public class TestStop implements Runnable{

    //1.設(shè)置一個(gè)標(biāo)志位
    private boolean flag=true;
    @Override
    public void run() {
       int i=0;
       while (flag){
           System.out.println("run...thread.."+i++);
       }
    }

    //2.設(shè)置一個(gè)公開(kāi)的方法停止線程,轉(zhuǎn)換標(biāo)志位
    public void stop(){
           this.flag=false;
    }


    public static void main(String[] args) {
        TestStop stop=new TestStop();
        new Thread(stop).start();


        for (int i = 0; i < 1000; i++) {
            System.out.println("main"+i);
            if (i==900){
                //調(diào)用stop方法,讓線程停止
                stop.stop();
                System.out.println("線程該停止了");
            }
        }
//        IntStream.range(0,1000).forEach(i->{
//            
//        });
    }
}

線程休眠sleep

每個(gè)對(duì)象都有一把鎖,sleep不會(huì)釋放鎖

1.網(wǎng)路延遲

            //模擬延遲
            try {
                Thread.sleep(200); //ms
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

2.倒計(jì)時(shí)等

 public static void main(String[] args) {
       try {
            tendown();
        } catch (InterruptedException e) {
            e.printStackTrace();
       }
  }
    public static void tendown() throws InterruptedException {
        int num=10;
        while (true){
            Thread.sleep(1000);
            System.out.println(num--);
            if(num<=0)
            {
                break;
            }
        }
    }
 public static void main(String[] args) {
        //打印系統(tǒng)當(dāng)前時(shí)間
        Date startTime=new Date(System.currentTimeMillis());
        while (true){
            try {
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
                startTime=new Date(System.currentTimeMillis());//更新時(shí)間
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

線程禮讓yield

//線程禮讓  禮讓不一定成功,由cpu重新調(diào)度
public class TestYield {
    public static void main(String[] args) {
        MyYield myYield=new MyYield();
        new Thread(myYield,"a").start();
        new Thread(myYield,"b").start();
    }
}
class MyYield implements  Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"線程開(kāi)始執(zhí)行");
        Thread.yield();
        System.out.println(Thread.currentThread().getName()+"線程停止執(zhí)行");
    }
}

線程強(qiáng)制執(zhí)行

//測(cè)試join方法  想象為插隊(duì)
public class TestJoin implements  Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("線程vip來(lái)了"+i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        //啟動(dòng)線程
        TestJoin testJoin=new TestJoin();
        Thread thread=new Thread(testJoin);
        thread.start();

        //主線程
        for (int i = 0; i < 1000; i++) {
            if (i==200){
                thread.join(); //插隊(duì)
            }
            System.out.println("main"+i);
        }
    }
}

觀察線程狀態(tài)

public class TestState {
    public static void main(String[] args) throws InterruptedException {
        Thread thread=new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("http://");
        });

        //觀察狀態(tài)
        Thread.State state=thread.getState();
        System.out.println(state);   //NEW

        //啟動(dòng)后
        thread.start();
        state=thread.getState();
        System.out.println(state);   //Run

        while (state != Thread.State.TERMINATED)
        {
            Thread.sleep(100);
            state=thread.getState();//更新線程狀態(tài)
            System.out.println(state);   //Run
        }
    }
}

線程的優(yōu)先級(jí)

//測(cè)試線程的優(yōu)先級(jí)
public class TestPriority {
    public static void main(String[] args) {
        //主線程默認(rèn)優(yōu)先級(jí)
        System.out.println(Thread.currentThread().getName()+"--->"+Thread.currentThread().getPriority());

        MyPriority myPriority=new MyPriority();

        Thread t1=new Thread(myPriority);
        Thread t2=new Thread(myPriority);
        Thread t3=new Thread(myPriority);
        Thread t4=new Thread(myPriority);
        Thread t5=new Thread(myPriority);
        Thread t6=new Thread(myPriority);
        //先設(shè)置優(yōu)先級(jí),在啟動(dòng)
        t1.start();
        t2.setPriority(1);
        t2.start();
        t3.setPriority(4);
        t3.start();
        t4.setPriority(Thread.MAX_PRIORITY);
        t4.start();
        t5.setPriority(-1);
        t5.start();
        t6.setPriority(11);
        t6.start();

    }
}
class MyPriority implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"--->"+Thread.currentThread().getPriority());
    }
}

守護(hù)線程

線程分為用戶線程和守護(hù)線程

//測(cè)試守護(hù)線程
public class TestDaemon {
    public static void main(String[] args) {
        God god=new God();
        You you=new You();
        Thread thread=new Thread(god);
        thread.setDaemon(true); //默認(rèn)是false表示用戶線程
        thread.start();

        new Thread(you).start();

    }
}

class God implements  Runnable{

    @Override
    public void run() {
      while (true){
          System.out.println("上帝保佑著你");
      }
    }
}
class You implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 36000; i++) {
            System.out.println("你活著"+i);
        }
        System.out.println("goodbye!!");
    }
}

線程同步機(jī)制

解決安全性問(wèn)題:隊(duì)列+鎖

1.synchronized 同步方法

默認(rèn)鎖的是this,如需鎖其他的,使用下面的同步塊

//synchronized 同步方法
    private  synchronized void buy(){
        if (ticketNums<=0){
            flag=false;
            return;
        }
        //模擬延遲
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //買票
        System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"張票");
    }

2.同步塊synchronized(Obj){}

鎖的對(duì)象是變化的量,需要增刪改的對(duì)象
obj稱之為同步監(jiān)視器,即監(jiān)視對(duì)象

public class UnsafeList {
    public static void main(String[] args) {
        List<String> list=new ArrayList<String>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                synchronized (list){
                    list.add(Thread.currentThread().getName());
                }
            }).start();
        }

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

lock

class A{
     //ReentrantLock 可重入鎖
     private final ReentrantLock lock=new ReentrantLock();
     public void f(){
       lock.lock();//加鎖
       try{
           //.....
        }
       finally{
          lock.unlock();//釋放鎖
        }
     }
   
}


synchronized與lock

  1. lock是顯示鎖需要手動(dòng)開(kāi)關(guān),synchronized是隱式鎖,出了作用域自動(dòng)釋放
  2. lock只有代碼塊鎖,synchronized有代碼塊鎖和方法鎖
  3. JVM將花費(fèi)更少的時(shí)間來(lái)調(diào)度線程,性能更好,更有擴(kuò)展性
  4. 優(yōu)先使用:Lock>同步代碼塊>同步方法

到此這篇關(guān)于Java多線程學(xué)習(xí)筆記的文章就介紹到這了,更多相關(guān)Java 多線程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • swagger中如何給請(qǐng)求添加header

    swagger中如何給請(qǐng)求添加header

    這篇文章主要介紹了swagger中如何給請(qǐng)求添加header,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • kaptcha驗(yàn)證碼組件使用簡(jiǎn)介解析

    kaptcha驗(yàn)證碼組件使用簡(jiǎn)介解析

    這篇文章主要介紹了kaptcha驗(yàn)證碼組件使用簡(jiǎn)介解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • MybatisPlusInterceptor依賴變紅如何解決,無(wú)法識(shí)別問(wèn)題

    MybatisPlusInterceptor依賴變紅如何解決,無(wú)法識(shí)別問(wèn)題

    這篇文章主要介紹了MybatisPlusInterceptor依賴變紅如何解決,無(wú)法識(shí)別問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • idea撤銷git?commit操作詳解

    idea撤銷git?commit操作詳解

    這篇文章主要為大家介紹了idea撤銷git?commit操作詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • 談?wù)凧ava中自定義注解及使用場(chǎng)景

    談?wù)凧ava中自定義注解及使用場(chǎng)景

    這篇文章主要介紹了談?wù)凧ava中自定義注解及使用場(chǎng)景,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • java獲取http請(qǐng)求的Header和Body的簡(jiǎn)單方法

    java獲取http請(qǐng)求的Header和Body的簡(jiǎn)單方法

    下面小編就為大家?guī)?lái)一篇java獲取http請(qǐng)求的Header和Body的簡(jiǎn)單方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-11-11
  • Java中的ReentrantReadWriteLock使用詳解

    Java中的ReentrantReadWriteLock使用詳解

    這篇文章主要介紹了Java中的ReentrantReadWriteLock使用詳解,ReentrantReadWriteLock是Java中的一個(gè)鎖實(shí)現(xiàn),它提供了讀寫(xiě)分離的功能,這種讀寫(xiě)分離的機(jī)制可以提高并發(fā)性能,特別適用于讀多寫(xiě)少的場(chǎng)景,需要的朋友可以參考下
    2023-11-11
  • java 實(shí)現(xiàn)多線程的方法總結(jié)

    java 實(shí)現(xiàn)多線程的方法總結(jié)

    這篇文章主要介紹了java 實(shí)現(xiàn)多線程的方法總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • Springboot整合logback的詳細(xì)教程

    Springboot整合logback的詳細(xì)教程

    這篇文章主要介紹了Springboot整合logback的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2024-01-01
  • Java設(shè)計(jì)模式之原型模式詳細(xì)解讀

    Java設(shè)計(jì)模式之原型模式詳細(xì)解讀

    這篇文章主要介紹了Java設(shè)計(jì)模式之原型模式詳細(xì)解讀,原型模式屬于創(chuàng)建型設(shè)計(jì)模式,用于創(chuàng)建重復(fù)的對(duì)象,且同時(shí)又保證了性能,該設(shè)計(jì)模式的好處是將對(duì)象的創(chuàng)建與調(diào)用方分離,需要的朋友可以參考下
    2023-12-12

最新評(píng)論