JAVA多線程基礎:基礎語法

  • 線程運行速度比進程速度快

實現多線程的3種方案

可以實現Thread類

  • 任何情況下,只要定義了多線程,多線程的啓動永遠只有一種方案,Thread類中的start()方法

  • 內部調用的是strat0(),這是一個JNI實現方法,JVM根據不同的系統實現不同的start0()方法

    import java.util.function.*;
    class MyThread extends Thread{
    	private String title;
    	public MyThread(String title){
    		this.title = title;
    	}
    	@Override
    	public void run(){
    		for(int i= 0;i< 10;i++){
    			System.out.println(this.title + "i = " + i);
    		}
    	}
    }
    public class JavaDemo{
        public static void main(String[] arges){
            MyThread myThread01 = new MyThread("TEST01 ");
    		myThread01.start();
            MyThread myThread02 = new MyThread("TEST02 ");
    		myThread02.start();
            MyThread myThread03 = new MyThread("TEST03 ");
    		myThread03.start();
        }
    }
    

    Runnable實現多線程

  • 1.8之後就變爲函數式接口,可以直接實現lambda函數式

  • 開發中首要考慮Runnable實現,並通過Thread.start()方法

  • 藉助構造方法:public Thread(Runnable target)實現

    • 這裏是實現接口,所以MyThread可以作爲一個正常的類,去繼承其他類或是實現多個接口
import java.util.function.*;
class MyThread implements Runnable{
	private String title;
	public MyThread(String title){
		this.title = title;
	}
	@Override
	public void run(){
		for(int i= 0;i< 10;i++){
			System.out.println(this.title + "i = " + i);
		}
	}
}
public class JavaDemo{
    public static void main(String[] arges){
        Thread thread = new Thread(new MyThread("TEST"));
		thread.start();
    }
}
  • Lambda函數式(超簡潔)

    public class JavaDemo{
        public static void main(String[] arges){
    		Runnable run = ()->{
    			System.out.println("這裏在多線程中執行");
    		};
            new Thread(run).start();
        }
    }
    
#更簡單的
import java.util.function.*;
public class JavaDemo{
    public static void main(String[] arges){
        new Thread(()->{
			System.out.println("dsfsdf");
		}).start();
    }
}
Thread與Runnable的關係
  • ````public class Thread extends Object implements Runnable{}```Thread類也是實現了Runnable接口的子類
  • 有上面瞭解到,多線程的方法主要都是由Thread實現的,所以操作系統的資源調用也是通過Thread調用的
  • Thread爲代理類,MyThread或者實現Runnable接口的類爲真實類
  • 多線程開發的本質是在於多個線程可以進行對統一資源的搶佔

Callable實現多線程

  • Runnable的缺點是,執行完畢後,無法給主線程一個返回值

  • 1.5之後實現的新方法java.util.concurrent.Callable接口,使用泛型返回數據

  • 方法流程圖

在這裏插入圖片描述

Runnable與Callable
  • Runnable是在JDK1.0的時候提出的多線程的實現接口,而Callable是JDK1.5之後提出來的

  • java.lang.Runnable接口之中只提出一個run()方法,並沒有返回值

  • java.util.concurrent.Callable接口提供有call()方法,可以有返回值;

    import java.util.concurrent.Callable;
    import java.util.concurrent.FutureTask;
    
    class MyThread implements Callable<String>{
    	@Override
    	public String call() throws Exception{
    		for(int i=0;i < 1000;i++){
    			System.out.println("==========" + i);
    		}
    		return "=====end========";
    	}
    }
    public class JavaDemo{
        public static void main(String[] arges)throws Exception{
            FutureTask<String> task = new FutureTask<>(new MyThread());
    		new Thread(task).start();
    		System.out.println(task.get());
        }
    }
    

其他小知識

多線程的狀態

狀態
  • 創建
  • start()
    • 就緒狀態
      • 阻塞狀態
    • 運行狀態
  • 終止
進程與休眠
  • 一個程序中可以啓動若干個JVM,每個JVM就是一個進程
  • 休眠可以設置爲毫秒和納秒2中精確度,如果被打斷會拋出Exception子類的異常,必須處理
  • 所有線程運行同一個方法時,也會有先後,並沒有絕對的一起執行

線程的名稱

  • 開發爲了獲得一些線程的操作,可以通過線程的名稱獲得

    • 構造方法:public Thread(Runnable target,String name)
    • 設置名稱:public final void setName(String name)
    • 取的名稱:public final String getName();
    • 獲得當前線程的方法:Thread.currentThread().getName()

線程中斷

  • 判斷是否被中斷:public boolean isInterrupted();//被中斷 返回true
  • 中斷線程執行:public void interrupt();

線程的強制執行

public class test {

    public static void main(String[] args) {
       Thread mainThread = Thread.currentThread();
       Thread thread = new Thread(()->{
           for (int x = 0; x < 100; x++){
               if (x == 3){
                   try {
                       mainThread.join();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
               System.out.println("thread == " + x);
           }
       });
        thread.start();
        for (int i = 0; i < 100; i++){
            System.out.println("霸道主線程mainThread == " + i);
        }
    }
}

線程的禮讓

  • 禮讓:public void yield()

  • 每次出現競爭的時候,都會禮讓一次,大部分時候會禮讓,但是不明顯

      public static void main(String[] args) {
           Thread thread = new Thread(()->{
               for (int x = 0; x < 100; x++){
                   if (x % 3 == 0){
                       Thread.yield();
                       System.out.println("===========我禮讓一次===========");
                   }
                   try {
                       Thread.sleep(100);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   System.out.println("thread == " + x);
               }
           });
            thread.start();
            for (int x = 0; x < 100; x++){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("霸道主線程mainThread == " + x);
            }
        }
    

優先級設置

  • 設置優先級:public final void setPriority(int new Priority);
    • 默認優先級: 5(NORM_PRIORITY)
    • 最高優先級:MAX_PRIORITY 10
    • 中等優先級:NORM_PRIORITY 5
    • 最低優先級:MIN_PRIORITY 1
  • 獲取優先級:public final int getPriority()

同步方法

同步代碼塊、同步方法

  • 同步代碼塊,速度會變慢

線程的等待機制

  • 死等:wait()
  • 設定等待時間 wait(long timeout,int nanos)
  • 喚醒第一個等待線程:notify()
  • 喚醒全部線程:notifyALL()
  • 禁用的方法:stop()、suspend()掛起、destroy()銷燬
  • 用全局變量去停止線程

守護線程

- 設置守護線程:public final void setDaemon(boolean on);
- 判斷是否爲守護線程:public final boolean isDaemon();
- 設置爲守護線程後,整體程序結束後,守護線程也將結束
- JVM最大的守護線程就是GC線程,程序結束,GC也一起結束

volatile

正常的變量處理步驟:
  • 獲取變量原有的數據內容副本
  • 利用副本爲變量進行數學計算
  • 將計算後的變量,保存到原始空間之中
volatile關鍵字
  • 表示不使用副本,而是直接操作變量,所以並不是同步操作,也需要同步關鍵字
volatile與syncharoniaed的區別
  • volaile主要在屬性上使用,而synchronized是在代碼塊與方法上使用的
  • volatile無法描述同步的處理,它只是一種直接內存的處理,避免的副本的操作,而synchronized是實現同步的
  • volatile配送syncharoniaed處理同步,可以更快的運行

StringBuffer

  • 線程安全的字符串添加方法,1.0之後提供的

  • 追加:new StringBUffer(“www.cn”).insert(4,“mldn”)在第4個開始追加

  • 部分刪除:buf.append(“www.mldn.com”).delete(4,8).insert(4,“bridge”);//“www.bridge.com”

  • 支付反轉:buf.reverse()

  • StringBuilder:非線程安全的效率更高,1.5之後才提供的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章