1. 程式人生 > >Java——多執行緒的簡單實現

Java——多執行緒的簡單實現

中高階架構師的必經之路:

高可用、高併發、高效能網站開發

多執行緒基本概念:

多個程序同時進

執行緒:排程和執行的單位(cpu的排程)

程序:作為資源分配的單位(作業系統的分配)

執行緒是程序的一部分

使用者執行緒和守護執行緒

使用者執行緒:java虛擬機器所有使用者執行緒dead後,程式就會結束

守護執行緒:輔助使用者執行緒進行工作,不適用於I/O輸入輸出以及計算操作,避免程式結束後,任務不能執行完。

守護執行緒使用情景:

1、JVM垃圾回收

2、記憶體管理

3、資料庫連線池監聽狀態等

多執行緒的實現

1、基礎Thread類,實現run方法

例項1:

//多實現少繼承://繼承也許需要繼承多個類而實現不需要考慮這些public class test10 {     //建立執行緒:1、繼承Thread+重寫run     //2、建立子類物件+start     public static void main(String[] args){     } }class MyThread extends Thread{     public void run(){         for(int i = 0;i<20;i++){             System.out.println("聽歌");         }     }     public static void

main(String[] args){         //啟動執行緒         MyThread my = new MyThread();         my.start();//兩條執行緒同時執行,不會互相干擾         for(int i = 0;i<20;i++){             System.out.println("跳舞");//cpu去調配         }     } }

執行結果

繼承Thread類,實現run方法,通過例項的start()方法,告知系統可以開始執行該run方法,根據系統排程器分配執行時間片,進行執行。

多次執行,執行結果不相同。

實現跳舞的執行緒和實現聽歌的執行緒不相同。

例項2(多執行緒與I/O結合:多執行緒實現圖片下載)

public class test11 {     public static void main(String[] args){         String url1 = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1540353806265&di=e4258c87892a1b4080891f0d03241a74&imgtype=0&src=http%3A%2F%2Fimg2.dwstatic.com%2Fnews%2F1809%2F401517849603%2F401517880783.jpeg";         String url2 = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1540948740&di=6ec8f3d51fdc501444cd58d47971db87&imgtype=jpg&er=1&src=http%3A%2F%2F07.imgmini.eastday.com%2Fmobile%2F20171102%2F20171102173205_2fb5db37f5a7fcb32d6054adcb21f28a_1.jpeg";         String url3 = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1540354085940&di=2aec582b87582ecb0426bede2462f987&imgtype=0&src=http%3A%2F%2Fpic.anzogame.com%2Flol%2Fnews%2F20140829%2F14092426723701_org.jpg";         MyThread2 dl1 = new MyThread2(url1,"E:/for_file/2.png" );         MyThread2 dl2 = new MyThread2(url2,"E:/for_file/3.png" );         MyThread2 dl3 = new MyThread2(url3,"E:/for_file/4.png" );         dl1.start();         dl2.start();         dl3.start();     } }class Downloadimg{     public void Download(String url, String path){         try {             FileUtils.copyURLToFile(new URL(url),new File(path) );         } catch (IOException e) {             e.printStackTrace();         }     } }class MyThread2 extends Thread{     private  String url;     private String path;     public MyThread2(String url,String path){         this.url = url;         this.path = path;     }     public void run() {         Downloadimg dli = new Downloadimg();         dli.Download(this.url,this.path );     } }

引用Commons IO jar包中的方法進行檔案內容的複製,其實變相於下載。

實現runnable介面

class MyThread implements Runnable{     public void run(){         for(int i = 0;i<5;i++){             System.out.println("聽歌");         }     }     public static void main(String[] args){         //建立實現類物件         MyThread my = new MyThread();         //建立代理類物件         Thread t = new Thread(my);         t.start();         for(int i = 0;i<5;i++){             System.out.println("跳舞");//cpu去調配         }     } }

實現介面,重寫run方法,然後建立子類物件和Thread類的代理物件,通過將子類物件以傳參的形式傳給代理物件,通過呼叫代理物件的start()方式進行排程。

如果只執行一次,可以如上進行編碼;

相比較繼承類,推薦實現介面的方法:

1、方便共享資源

2、繼承類單繼承的侷限性

Thread類的原始碼:

引數1:可執行目標

引數2:姓名(給執行緒賦予稱號)

例項:

public class test10 {     public static void main(String[] args){         MyThread my = new MyThread();         new Thread(my,"小二").start();         new Thread(my,"小一").start();     } }class MyThread implements Runnable{     private int num = 20;     @Override     public void run() {         while(true){             if(num<0){                 break;             }             System.out.println(Thread.currentThread().getName()+"----"+num--);         }     } }

單任務多執行緒並給每個執行緒設定名字

執行結果

當一個任務有多個代理共同執行時,如果有網路延遲等問題,會導致併發,這時候就是執行緒不安全,需要進行處理。

實現Callable的Call方法

public class test10 {     public static void main(String[] args) {         //建立執行服務         MyThread my1 = new MyThread();         MyThread my2 = new MyThread();         ExecutorService es = Executors.newFixedThreadPool(2);         //提交執行         Future<String> r1 = es.submit(my1);         Future<String> r2 = es.submit(my2);         //獲取結果         try {             String re1 = r1.get();             System.out.println(re1);             String re2 = r2.get();             System.out.println(re2);         } catch (InterruptedException e) {             e.printStackTrace();         } catch (ExecutionException e) {             e.printStackTrace();         }         //關閉服務         es.shutdownNow();     } }class MyThread implements Callable<String> {     @Override     public String call() throws Exception {         return "有些失望是不可避免的,但大部分的失望,都因為你高估了自己。";     } }

執行結果

比較複雜,暫時只需要瞭解:

繼承Callable介面,實現call方法,確定返回值型別。

執行操作:

1、建立執行服務 ExecutorService es = Executors.newFixedThreadPool(2);

2、提交任務  Future<String> r1 = es.submit(my1);

3、接受返回值 String r = r1.get();

4、結束服務 es.shutdownNow();