天天看點

程式,程序,線程;繼承Thread類;用多線程下載下傳圖檔;實作Runnable接口;多線程龜兔賽跑;callable下載下傳圖檔(了解)

程式.程序(Process).線程(Thread)

在作業系統中運作的程式就是程序,程式是代碼,是死的,是一個靜态的概念,而程序是執行程式的一次執行過程,是一個動态的概念,是系統資源配置設定的機關,比如QQ,LOL,IDE等等。。

一個程序可以有多個線程,如在看視訊時,可以同時聽聲音,看圖像,看彈幕,等等。

即使一個程序什麼都不幹,裡面也有一個main線程(主線程) ,線程就是獨立的執行路徑。

注意:很多多線程是模拟出來的,真正的多線程是隻有多個CPU,即多核,如 伺服器。而模拟出來的多線程在一個CPU下,同一時間隻執行一個代碼,隻是切換的很快而已。

建立線程之一:

繼承Thread (不建議使用,避免OOP單繼承局限性)

  1. 自定義線程類繼承Thread類
  2. 重寫run()方法,編寫線程執行體
  3. 建立線程對象,調用start()方法啟動線程

執行個體如下:

public class TestThread1 extends Thread {
    @Override
    public void run() {
        super.run();
        //run方法線程體
        for (int i = 0; i < 20; i++) {
            System.out.println("run線程。。。。");
        }
    }
    
    public static void main(String[] args) {
        //main線程,主線程
        //建立線程對象,調用start方法開啟線程
        TestThread1 testThread1 = new TestThread1();
        testThread1.start();
        for (int i = 0; i < 200; i++) {
            System.out.println("main......");
        }
    }
}
           
程式,程式,線程;繼承Thread類;用多線程下載下傳圖檔;實作Runnable接口;多線程龜兔賽跑;callable下載下傳圖檔(了解)

注意:線程開啟不一定立即執行,由cpu排程執行。調用多個線程對象的start()方法,執行順序是不一定的。

用多線程下載下傳圖檔

下載下傳一個commons IO包,他是别人針對開發IO流功能的工具類庫,直接百度搜尋即可,将其拷到項目裡的一個建立檔案夾裡,此時他不能直接用,要右鍵此檔案夾選中Add as Library添加到庫裡面。此時如果檢視項目資源目錄,裡面就有一個libraries。

1.先寫一個下載下傳器,裡面有一個下載下傳方法,它是通過FileUtils這個工具類的copyURLToFile方法将圖檔下載下傳下來。

//下載下傳器,因為這個定義的類全都放在了一個頁面是以沒有public,一個java類中隻能有一個public class類
class WebDownLoader{
    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異常,dowmloader方法出現問題");
       }
    }
}
           

2.要實作一個線程類,然後寫一個有參構造,用來丢入位址和名字,再然後重寫run()方法,它是下載下傳圖檔線程的執行體。最後在main()函數中通過三個構造器建立三個線程,然後用三個start()方法把這三個線程同時啟動起來。

public class TextThread2 extends Thread{
    private String url;//網絡圖檔位址
    private String name;//儲存的檔案名

    public TextThread2(String url,String name){  //寫構造器
       this.url=url;
       this.name=name;
    }
    
    @Override
    public void run() {
           WebDownLoader webDownLoader = new WebDownLoader();
           webDownLoader.downLoader(url,name);
        System.out.println("下載下傳了檔案名為:"+name);
    }

    public static void main(String[] args) {
        TextThread2 t1=new TextThread2("此處寫要下載下傳圖檔的位址","給想要下載下傳的圖檔命名");
        TextThread2 t2=new TextThread2("此處寫要下載下傳圖檔的位址","給想要下載下傳的圖檔命名");
        TextThread2 t3=new TextThread2("此處寫要下載下傳圖檔的位址","給想要下載下傳的圖檔命名");
        t1.start();
        t2.start();
        t3.start();
    }
}
           

建立線程方法二:

實作Runnable(推薦該方式)可避免單繼承局限性,靈活,友善同一個對象被多個線程使用

  1. 定義MyRunnable類實作Runnable接口
  2. 重寫run()方法,編寫線程執行體
  3. 建立線程對象,調用start()方法啟動線程

執行個體如下:

和繼承Thread類那種方法差不多,這就是将Runable接口的實作類對象丢入Thread裡面,調用start()啟動.

public class TextThread3 implements Runnable {
    @Override
    public void run() {
        //run()方法線程體
        for (int i = 0; i < 200; i++) {
            System.out.println("run"+i);
        }
    }

    public static void main(String[] args) {
        //建立runnable接口的實作類對象
        TextThread3 textThread3 = new TextThread3();
        //建立線程對象,通過線程對象來開啟我們的線程,代理
        Thread thread = new Thread(textThread3);
        thread.start();
        //這兩句等價于 new Thread(testThread3).start();

        for (int i = 0; i < 1000; i++) {
            System.out.println("main"+i);
        }
    }
}
           

用runnable多線程下載下傳圖檔

和第一種方式比較隻需改動兩處——畫“***************************”處

public class TextThread2 implements Runnable{              ***************************************
    private String url;//網絡圖檔位址
    private String name;//儲存的檔案名

    public TextThread2(String url,String name){  //寫構造器
       this.url=url;
       this.name=name;
    }
    
    @Override
    public void run() {
           WebDownLoader webDownLoader = new WebDownLoader();
           webDownLoader.downLoader(url,name);
        System.out.println("下載下傳了檔案名為:"+name);
    }

    public static void main(String[] args) {
        TextThread2 t1=new TextThread2("此處寫要下載下傳圖檔的位址","給想要下載下傳的圖檔命名");
        TextThread2 t2=new TextThread2("此處寫要下載下傳圖檔的位址","給想要下載下傳的圖檔命名");
        TextThread2 t3=new TextThread2("此處寫要下載下傳圖檔的位址","給想要下載下傳的圖檔命名");
        new Thread(t1).start();                          **************************************
        new Thread(t2).start();                          **************************************
        new Thread(t3).start();                          **************************************
    }
}
//下載下傳器
class WebDownLoader{
    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異常,dowmloader方法出現問題");
       }
    }
}
           

一個對象被多個線程使用的執行個體:

//多個線程同時操作一個Runnable接口的對象
//買火車票的例子
public class TestThread4 implements Runnable{

    //票數
    private int ticketNums = 10;

    @Override
    public void run() {
        while(true){
            if(ticketNums<=0){
                break;
            }
            //模拟延時,200毫秒,0.2秒
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"拿到了"+ticketNums--+"票");
        }
    }


    public static void main(String[] args) {
        //一個資源
        TestThread4 testThread4 = new TestThread4();
        //多個代理
        new Thread(testThread4,"小紅").start();
        new Thread(testThread4,"小白").start();
        new Thread(testThread4,"小黑").start();
    }
}
           

多線程龜兔賽跑

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(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            boolean flag = gameOver(i);
            if (flag) {
                break;
            }
            System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");
        }
    }

    //判斷是否完成比賽
    private boolean gameOver(int steps) {
        //判斷是否有勝利者
        if (winner != null) {
            return true;
        } else if (steps >= 100) {
                //Thread.currentThread()這是Theard類的currentThread()方法,意思就是”目前線程“
                winner = Thread.currentThread().getName();
                System.out.println("winner is" + winner);
                return true; }
        else {
            return false;
        }
    }


    public static void main(String[] args) {
        Race race = new Race();
        //由于兩個線程公用一個資源,都用run方法,誰先跑完執行方法裡面的break,另一個也就跑不了了
        new Thread(race,"兔子").start();
        new Thread(race,"烏龜").start();

    }
}
           

Callable下載下傳圖檔(了解)

程式,程式,線程;繼承Thread類;用多線程下載下傳圖檔;實作Runnable接口;多線程龜兔賽跑;callable下載下傳圖檔(了解)
程式,程式,線程;繼承Thread類;用多線程下載下傳圖檔;實作Runnable接口;多線程龜兔賽跑;callable下載下傳圖檔(了解)

繼續閱讀