JAVA | 線程(三)控制線程

一、Join線程

當前線程調用了 另一個線程的join() 方法,當前線程會阻塞,直到 被join的線程執行完成後 纔會繼續執行。

public class JoinThread extends Thread{
        JoinThread(String name){
            super(name);
        }

        @Override
        public void run() {
            super.run();
            for (int i=0;i<100;i++){
                Log.e("testthread",getName() +","+ i);
            }
        }
    }

mBntFun4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new JoinThread("新線程").start();
                for (int i = 0;i<100;i++){
                    Log.e("testthread",Thread.currentThread().getName() +","+ i);
                    if (i == 20){
                        // 啓動新線程
                        JoinThread joinThread = new JoinThread("join線程");
                        joinThread.start();
                        try {
                            //1. 調用新線程的join方法,當前線程會阻塞,知道join的線程執行完成
                            joinThread.join();

                            // 2.當前線程最多等待1毫秒,超過20毫秒Join的線程還沒有執行完,則不再等待
                            //joinThread.join(1);
                            
                            //3. 當前線程最多等待1毫秒加10毫微秒(一般不用這個,因爲程序無法精確到毫微秒)
                            //joinThread.join(1,10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });

在這裏插入圖片描述
在這裏插入圖片描述

說明
join方法有以上代碼的三種重載方式

二、後臺線程(守護線程、精靈線程)

  1. 有些線程在後臺運行,爲其他線程提供服務,比如JVM垃圾回收線程
  2. 當所有的前臺線程死亡,那後臺線程也會隨之死亡,因爲當前臺進程都死亡後,就沒有運行的必要了,虛擬機也就退出了,後臺進程也就死亡了。
  3. 主線程默認是前臺線程,前臺線程創建的子線程是前臺線程,後臺線程創建的子線程是後臺線程
  4. 調用線程的 setDaemon(true) 設置爲後臺線程
  5. 調用線程 isDaemon() 判斷是否是後臺線程
  6. setDaemon要在start()之前調用
class FirstThread extends Thread{
        private int i;
        @Override
        public void run() {
            super.run();
            for (;i < 1000; i++){
                Log.e("testthread",getName() +","+ i);
            }
        }
    }
 mBntFun5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FirstThread thread = new FirstThread();
                // 要在start()之前調用
                thread.setDaemon(true);
                //啓動線程
                thread.start();
                
                for (int i=0;i<10;i++){
                    Log.e("testthread",Thread.currentThread().getName() +","+ i);

                }
                // 主線程運行到這就結束了,後臺線程也隨之結束,所以thread並不會打印到 999
            }
        });

三、線程睡眠 :sleep(是Thread的靜態方法)

可以讓正在執行的線程暫停一段時間,進入阻塞狀態

mBntFun5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                for (int i=0;i<10;i++){
                    Log.e("testthread",Thread.currentThread().getName() +","+ new Date());
                    try {
                        //讓主線程睡1毫秒
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

在這裏插入圖片描述說明
從上面的運行結果可以看到,線程每隔一秒打印一次

  1. sleep也有兩種重載方式:
  • void sleep(long millis) : 暫停多少毫秒
  • void sleep(long millis, int nanos):暫停多少毫秒加毫微秒(一般不用這個)
  1. 線程調用sleep()進入阻塞後,在睡眠時間內,不會獲得執行的機會即便系統中沒有其他線程在執行,處於sleep狀態的線程也不會執行

四、線程讓步 :yield(靜態方法)

可以暫停當前的線程,讓它進入就緒狀態,並不會阻塞該線程

class FirstThread extends Thread{
        FirstThread(String name){
            super(name);
        }

        @Override
        public void run() {
            super.run();
            for (int i=0;i < 100; i++){
                Log.e("testthread",getName() +","+ i);
                if (i == 20){
                    Thread.yield();
                }
            }
        }
    }

mBntFun5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FirstThread thread1 = new FirstThread("高級");
                thread1.setPriority(Thread.MAX_PRIORITY);
                thread1.start();

                FirstThread thread2 = new FirstThread("低級");
                 thread2.setPriority(Thread.MAX_PRIORITY);
                thread2.start();
            }
        });

未設置優先級設置了優先級說明

  1. 通過**setPriority()**設置線程的優先級
  2. 調用yield()後,只有和當前線程同級或者比他優先級高的纔會獲得執行的機會
  3. 沒有比它優先級高的線程,調用yield()後當前線程繼續執行
sleep()和yield()的區別:
  1. 優先級:sleep()調用後,不會理會其他線程的優先級;yield需要
  2. 狀態:調用sleep()後會進入阻塞狀態,經過阻塞事件纔會進入就緒狀態;而yield直接就進入就緒狀態了
  3. 異常:調用sleep後會拋出InterruptedException異常,而yield沒有拋出任何異常
  4. 可移植性:sleep()有更好的可移植性,**不建議用yield()來控制併發線程

五、改變線程的優先級

  1. 每個線程的優先級都和創建它的父線程優先級相同
  2. main線程具有普通優先級
  3. 設置優先級:
    setPriority(1~10)
    public static final int MAX_PRIORITY = 10;
    public static final int MIN_PRIORITY = 1;
    public static final int NORM_PRIORITY = 5;
  1. 返回優先級:
    getPriority()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章