多線程停止

多線程停止的方法

  1. 設置一個標誌位。(無法處理線程阻塞時停止的問題)
  2. 調用Thread類提供的stop方法強行關閉線程。
    這個方法已經不推薦使用了,因爲會產生不完整的數據。
class ThreadDemo extends Thread{
    private boolean flag=true;
    public void setflag(boolean flag){
        this.flag=flag;
    }
    @Override
    public void run() {
        while(flag){
            System.out.println("李明建是頭豬");
        }
    }
}
public class Solution {
    public static void main(String[] args) throws InterruptedException {
        Thread th1=new ThreadDemo();
        th1.start();
        Thread.sleep(1000);
        //((ThreadDemo) th1).setflag(false) ;
        th1.stop();
    }
}

  1. 調用Thread類提供的interrupt();
    a.若線程中沒有使用類似sleep/wait/join時,調用此線程對象的interrupt方法並不會中斷線程,只是簡單地將線程的狀態置爲interrupt而已,我們可以根據此狀態來進一步確定如何處理線程。
    Thread類提供的public boolean isInterrupted()可以檢測當前線程狀態是否爲中斷狀態。
    b.若線程中調用了阻塞線程的方法sleep()/wait()/join(),此時再調用線程的interrupt方法時會拋出異常,同時將線程狀態還原(isInterrupted=false)。
class ThreadDemo extends Thread{
    @Override
    public void run() {
        while(!Thread.currentThread().isInterrupted()){
            System.out.println("當前線程的狀態"+Thread.currentThread().isInterrupted());
        }
        if(Thread.currentThread().isInterrupted())
            System.out.println("豬");
    }
}
public class Solution {
    public static void main(String[] args) throws InterruptedException {
        Thread th1=new ThreadDemo();
        th1.start();
        Thread.sleep(1000);
        th1.interrupt();
    }
}

1.Thread.interrupted() 判斷當前線程的中斷標誌被設置,清除中斷標誌
2. Thread.currentThread().isInterrupted() 判斷指定線程的中斷標誌被設置,不清除中斷標誌

public class Solution2 {
        /**
         * interrupt 可以通過異常方式通知
         */
        private static class MyThread1 extends Thread {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(10000000);
                    } catch (InterruptedException e) {
                        // 我收到了中斷通知
                        System.out.println(isInterrupted());
                        break;
                    }
                }
                System.out.println("退出");
            }
        }

        private static class MyThread2 extends Thread {
            @Override
            public void run() {
                while (!isInterrupted()) {
                }
                // 通過判斷中斷狀態退出,狀態不會被重置
                System.out.println(isInterrupted());
                System.out.println("退出");
            }
        }

        private static class MyThread3 extends Thread {
            @Override
            public void run() {
                while (!Thread.interrupted()) {
                }
                // 通過判斷中斷狀態退出,狀態被重置
                System.out.println(Thread.interrupted());
                System.out.println("退出");
            }
        }

        public static void main(String[] args) {
//            MyThread1 t1 = new MyThread1();
//            t1.start();
//            t1.interrupt();//false
//            MyThread2 t2 = new MyThread2();
//            t2.start();
//            t2.interrupt();//true
            MyThread3 t3 = new MyThread3();
            t3.start();
            t3.interrupt();//false
        }
    }

線程優先級

  1. 指的是優先級越高越有可能先執行
  2. getPriority() setPriority(int priority)
  3. 線程的繼承性:若在一個線程中創建了子線程,默認子線程與父線程的優先級相同。

守護線程

    作爲陪伴線程,只要在JVM中存在有任何一個用戶線程沒有終止,守護線程就一直工作。
  默認創建的線程都是用戶線程,包括主線程。通過setDaemon(true)將線程對象設置爲守護線程。
典型的守護線程:垃圾回收線程

線程同步(分工,同步,互斥)

1.互斥:多線程併發時,某一時刻只能有一個線程訪問共享資源。
2.鎖:一把鎖保護一個相應資源,不同鎖保護的不同的資源/對象
3.Java中鎖的實現
使用synchroinzed關鍵字爲程序邏輯上鎖,有兩種用法:

 a.同步代碼塊:
synchroinzed(鎖的對象|Object類及其子類){
        //此處代碼塊在任意時刻只能有一個進程進入
        }
class Demo extends Thread{
    private int ticket;
    public Demo(int ticket) {
        this.ticket=ticket;
    }
    @Override
    public void run() {
        //條件處只能在某一時刻只有一個線程,需要爲程序段上鎖
        for(int i=0;i<100;i++){
            //需要在判斷出上鎖
            synchronized (this){
                //在任意時刻只有一個線程能進入條件判斷
            if(ticket>0) {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() +"還剩下" + ticket-- + "票");
            }
            }
        }
    }
}
public class Solution3 {
    public static void main(String[] args) {
        Demo a=new Demo(100);
        Thread th1=new Thread(a,"A");
        Thread th2=new Thread(a,"B");
        Thread th3=new Thread(a,"C");
        th1.start();
        th2.start();
        th3.start();
    }
}

b. 同步方法:直接在方法聲明上使用 synchronized,此時表示同步方法在任意時刻只能有一個線程進入。

//默認鎖的是this
public synchronized void sell(){
}
class Demo extends Thread{
    private int ticket;
    public Demo(int ticket) {
        this.ticket=ticket;
    }
    @Override
    public void run() {
        //條件處只能在某一時刻只有一個線程,需要爲程序段上鎖
   for(int i=0;i<100;i++){
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                sell();
        }
    }
    //在任意時刻只能有一個線程進入此方法
    public synchronized void sell() {
        if (ticket > 0) {
            System.out.println(Thread.currentThread().getName() + "還剩下" + ticket-- + "票");
        }
    }
}
public class Solution3 {
    public static void main(String[] args) {
        Demo a=new Demo(100);
        Thread th1=new Thread(a,"A");
        Thread th2=new Thread(a,"B");
        Thread th3=new Thread(a,"C");
        th1.start();
        th2.start();
        th3.start();
    }
}
若synchronized修飾的是靜態的方法或synchronized(類名稱.class)synchronized鎖的都是當前類的反射對象(全局唯一)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章