JAVA | 線程(一)線程的創建

進程和線程的區別:

1.進程有以下幾個特點:

  • 獨立性:是系統中獨立存在的實體。有自己的資源地址空間,沒有進程的允許,其他進程不允許訪問該進程的地址空間
  • 動態性:程序是一個靜態的指令集合,而進程是一個正在系統中活動的指令集合進程有自己的生命週期和各種不同的狀態
  • 併發性:多個進程可以在單個處理器上併發執行而互不影響

2.併發性並行性的區別:

  • 併發性:多個指令在多個處理器上同時執行
  • 並行性:同一時刻只能有一條指令執行,而多個進程指令快速輪換執行,看起來就像是多個進程同時執行的樣子

3.線程進程的區別:

  • 線程也叫輕量級進程
  • 線程可以有自己的堆棧、程序計數器、局部變量,但不擁有系統資源,與父進程的其他線程共享該進程所擁有的全部資源
  • 一個程序運行後至少有一個進程,一個進程可以包括多個線程,但至少有一個線程

4.多線程的優點

  • 創建進程需要系統爲它分配系統資源,創建線程的代價小,效率會更高
  • 進程直接不能共享內存,線程直接共享非常容易
  • Java語言內置了多線程功能的支持,而不只是作爲底層操作系統的調度方式,簡化了多線程變成

線程的創建和啓動:

有以下三種方式:

  • 繼承Thread
  • 實現Runnable接口
  • 實現Callable接口

(1)繼承Thread

// 繼承Thread類
class FirstThread extends Thread{
		// 這個是**實例屬性**,不是局部變量
        private int i;
        @Override
        public void run() {
            super.run();
            for (;i < 100; i++){
                Log.e("testthread",getName() +","+ i);
            }
        }
    }

mBntFun1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                for (int i = 0;i < 100;i++){
                    
                    Log.e("testthread",Thread.currentThread() +","+ i);
                    
                    if (i == 20){
                        // 創建並啓動第一個線程
                        new FirstThread().start();

                        // 創建並啓動第二線程
                        new FirstThread().start();
                    }
                }
            }
        });

在這裏插入圖片描述
說明
(1)定義一個類繼承Thread,重寫run()方法,裏面代表線程需要完成的任務,run()就是線程執行體
(2)創建Thread子類的實例,即創建了子線程
(3)通過調用start()方法啓動線程
(4)因爲是繼承的Thread,直接用this代表當前線程。getName()返回線程的名字。
(5)通過Thread來創建線程類的時候,多個線程之間
無法共享線程類的實例屬性

(2)實現Runnable接口

class SecondRunnable implements Runnable{
        private int i;
        @Override
        public void run() {
            for (;i < 100; i++){
                Log.e("testthread",Thread.currentThread().getName() +","+ i);
            }
        }
    }

mBntFun2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                for (int i = 0;i < 100;i++){

                    Log.e("testthread",Thread.currentThread().getName() +","+ i);

                    if (i == 20){
                        SecondRunnable sr = new SecondRunnable();
                        // 創建並啓動第一個線程
                        new Thread(sr,"thread--1").start();

                        // 創建並啓動第二線程
                        new Thread(sr,"thread--2").start();
                    }
                }
            }
        });

在這裏插入圖片描述
== 說明 ==
(1)創建Runnable的實例,作爲Thread的target,new Thread(target,name)
(2)Runnable裏面的run()還是線程執行體,實際的線程仍然是Thread實例
(3)實現Runnable接口的時候,如果想獲取到當前線程,只能用Thread.currentThread()
(4)採用Runnable創建的多個線程可以共享線程類(實際上是線程的target類)的實體屬性,因爲這種情況下創建的Runnable只是Thread的target,兩個線程可以共享一個target。

使用Callable和Future創建線程

public class ThirdThread implements Callable<Integer>{
        private int i = 0;
        @Override
        public Integer call() throws Exception {
            for (;i < 100; i++){
                Log.e("testthread",Thread.currentThread().getName() +","+ i);
            }
            return i;
        }
    }

mBntFun3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ThirdThread callable = new ThirdThread();
                FutureTask<Integer> future = new FutureTask<Integer>(callable);

                for (int i = 0;i < 100;i++){

                    Log.e("testthread",Thread.currentThread().getName() +","+ i);

                    if (i == 20){
                        new Thread(future,"線程1").start();
                    }
                }
                try {
                    Log.e("testthread","返回值:"+future.get());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
        });

說明
(1)創建Callable的實現類,實現run方法,run()仍然是線程執行體
(2)創建Callable的實例,使用FutureTask類來包裝Callable對象,該FutureTask封裝了Callable中call(()的返回值
(3)使用FutureTask對象作爲Thread的target
(4)調用FutureTask對象的get()方法獲得子線程執行結束後的返回值;

補充說明

Future接口:

  • public boolean cancel(boolean mayInterruptIfRunning):
    取消FutureTask關聯的Callable任務

  • public V get():
    獲得call()的返回值,調用該方法會造成線程阻塞,必須等到子線程結束後纔會得到返回值

  • public V get(long timeout, TimeUnit unit)
    超過timeout和Unit指定的時間,還沒有得到返回值,則會拋出 TimeoutException

  • public boolean isCancelled()
    在Callable任務正常完成前被取消,則返回true

  • public boolean isDone()
    如果Callable任務已經完成,則返回true

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