java執行緒實現的三種方式以及靜態代理

Sprinining發表於2021-03-13

執行緒

  • 一個程式中若開闢多個執行緒,執行緒的執行由排程器控制,先後順序不能人為干預。

  • 實現方式

    1. 繼承 Thread類

      • 呼叫run方法,只有主執行緒一條路

      • 呼叫start方法,主執行緒和子執行緒並行交替執行

      • public class MyThread extends Thread{
        
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    System.out.println("xixi");
                }
            }
        
            public static void main(String[] args) {
        
                MyThread myThread = new MyThread();
                //myThread.run();只有主執行緒一條路,先xixi後haha
                //開啟執行緒,不一定立刻執行,由cpu排程
                myThread.start();//同時執行,xixi、haha交替
        
                //main執行緒
                for (int i = 0; i < 20; i++) {
                    System.out.println("haha");
                }
            }
        
        }
        
      • 匯入common-io.jar下載圖片

        import org.apache.commons.io.FileUtils;
        
        import java.io.File;
        import java.io.IOException;
        import java.net.URL;
        
        public class MyThread2 extends Thread{
        
            private String url;
            private String name;
        
            public MyThread2(String url, String name){
                this.name = name;
                this.url = url;
            }
        
            @Override
            public void run() {
                WebDownloader webDownloader = new WebDownloader();
                webDownloader.downloader(url, name);
                System.out.println("下載了檔名為" + name);
        
            }
        
            public static void main(String[] args) {
                MyThread2 t1 = new MyThread2("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3246675119,2528014287&fm=26&gp=0.jpg", "csgo1.jpg");
                MyThread2 t2 = new MyThread2("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3246675119,2528014287&fm=26&gp=0.jpg", "csgo2.jpg");
                MyThread2 t3 = new MyThread2("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3246675119,2528014287&fm=26&gp=0.jpg", "csgo3.jpg");
        
                t1.start();
                t2.start();
                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("downloader異常");
                } finally {
                }
            }
        }
        
    2. 實現Runnable介面

      • 推薦使用,避免單繼承侷限性,靈活方便,方便同一個物件被多個執行緒使用

      public class MyThread3 implements Runnable{
          @Override
          public void run() {
              for (int i = 0; i < 20; i++) {
                  System.out.println("xixi");
              }
          }
      
          public static void main(String[] args) {
      
              //建立實現runnable介面的類物件
              MyThread3 myThread3 = new MyThread3();
              //建立執行緒物件,通過執行緒物件啟動執行緒,代理
              new Thread(myThread3).start();
      
      
              for (int i = 0; i < 20; i++) {
                  System.out.println("haha");
              }
          }
      }
      
      • 多執行緒同時操作一個物件

        public class MyThread4 implements Runnable{
        
            private int ticketNums = 10;
        
            @Override
            public void run() {
                while (true){
                    if(ticketNums <= 0)
                        break;
        
                    //模擬延時
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "拿到了第" + ticketNums-- + "張票");
                }
            }
        
            public static void main(String[] args) {
                MyThread4 myThread4 = new MyThread4();
                new Thread(myThread4, "haha").start();
                new Thread(myThread4, "xixi").start();
                new Thread(myThread4, "hehe").start();
        
            }
        
        }
        //多個執行緒操作同一個資源時,執行緒不安全,資料紊亂
        /*
        haha拿到了第9張票
        xixi拿到了第8張票
        hehe拿到了第10張票
        hehe拿到了第6張票
        xixi拿到了第7張票
        haha拿到了第5張票
        hehe拿到了第4張票
        haha拿到了第4張票
        xixi拿到了第4張票
        xixi拿到了第2張票
        hehe拿到了第3張票
        haha拿到了第1張票
         */
        
    3. 實現Callable介面

      • 可以定義返回值、可以丟擲異常

      • import org.apache.commons.io.FileUtils;
        
        import java.io.File;
        import java.io.IOException;
        import java.net.URL;
        import java.util.concurrent.*;
        
        public class MyCallable implements Callable<Boolean> {
        
            private String url;
            private String name;
        
            public MyCallable(String url, String name){
                this.name = name;
                this.url = url;
            }
        
            @Override
            public Boolean call() throws Exception {
                WebDownloader webDownloader = new WebDownloader();
                webDownloader.downloader(url, name);
                System.out.println("下載了檔名為" + name);
                return true;
            }
        
            public static void main(String[] args) throws ExecutionException, InterruptedException {
                MyCallable t1 = new MyCallable("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3246675119,2528014287&fm=26&gp=0.jpg", "csgo1.jpg");
                MyCallable t2 = new MyCallable("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3246675119,2528014287&fm=26&gp=0.jpg", "csgo2.jpg");
                MyCallable t3 = new MyCallable("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3246675119,2528014287&fm=26&gp=0.jpg", "csgo3.jpg");
        
                //建立執行服務
                ExecutorService ser = Executors.newFixedThreadPool(3);
        
                //提交執行
                Future<Boolean> r1 = ser.submit(t1);
                Future<Boolean> r2 = ser.submit(t2);
                Future<Boolean> r3 = ser.submit(t3);
        
                //獲取結果
                boolean rs1 = r1.get();
                boolean rs2 = r2.get();
                boolean rs3 = r3.get();
        
                //關閉服務
                ser.shutdown();
            }
        
        
        }
        
        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("downloader異常");
                } finally {
                }
            }
        }
        
  • 靜態代理

    • 真實物件和代理物件都要實現同一個介面

    • 代理物件要代理真實角色

    • 代理物件可以做很多真實物件做不了的事情

    • 真實物件專注做自己的事情

    • public class StaticProxy {
          public static void main(String[] args) {
      
              You you = new You();
      
              //代理真實物件runnable
              new Thread(()-> System.out.println("haha")).start();
              
              //代理真實物件you
              new WeddingCompany(new You()).HappyMarry();
      
              WeddingCompany weddingCompany = new WeddingCompany(you);
              weddingCompany.HappyMarry();
          }
      }
      
      interface Marry{
          void HappyMarry();
      }
      
      //真實角色
      class You implements Marry{
          @Override
          public void HappyMarry() {
              System.out.println("marry!");
          }
      }
      
      //代理角色
      class WeddingCompany implements Marry{
          
          private Marry target;
      
          public WeddingCompany(Marry target){
              this.target = target;
          }
      
          @Override
          public void HappyMarry() {
              before();
              this.target.HappyMarry();//真實物件
              after();
          }
      
      
          public void before() {
              System.out.println("before marry");
          }
          public void after() {
              System.out.println("after marry");
          }
      }
      

相關文章