java多線程編程

線程基本概念java

進程:內存中正在進行的一個程序多線程

線程:進程中的一個執行流程併發

多線程:有兩個 或者 兩個以上併發的執行流程ide

線程的生命週期,線程分爲如下五種狀態this

  • (新建) New Thread();
  • (就緒) start();
  • (運行) run();
  • (阻塞) 暫停執行spa

    • sleep(就像咱們作總結睡着了),join(讓其餘人先作,就像作總結時中間讓其餘人講話)阻塞

      sleep:等待多少毫秒;超過了以後回覆就緒狀態等待cpu調用執行
      join:等待其餘線程執行完,線程A調用了線程B的join();方法,那麼線程A等線程B執行完再執行線程

    • 同步(排隊)
    • wait(暈過去了)
  • (死亡)

線程圖解:對象

主線程blog

當Java程序啓動時,一個線程馬上運行,該線程通 常叫作程序的主線程(main thread),==它是程序 開始時就執行的==。繼承

主方法就是主線程的任務 main();

public class TestThreadMain {

    public static void main(String[] args) {

        // 得到當前的線程                      主線程名字,優先級,主線程組

        System.out.println(Thread.currentThread());//Thread[main,5,main]

        System.out.println(Thread.currentThread().getName());//main

    }

}

問題:啓動一個java應用程序至少啓動幾個主線程?

會先啓動兩個線程:一個主線程,一個垃圾回收線程

子線程

默認的名字:Thread —— 數字

建立子線程

  • 方式一:繼承自Thread類
  • 方式二:實現Runnable 接口

區別:
1. 繼承Thread類,繼承了Thread類的全部能夠繼承的;Runnable接口,只有run();
2. Runnable接口有利於資源共享

但願主線程最後結束

  • sleep() 暫停多長時間
  • isAlive() 判斷線程仍在運行,isAlive()方法返回true,若是丌是則 返回false。
  • join() 等待一個線程執行完

/** 建立子線程示例代碼 */

//建立子線程方法一:繼承自Thread類  
class MyThread extends Thread{
    MyThread(String name){
        super(name);
    }

    //子線程的任務功能在run中
    @Override
    public void run() {
        for(int i = 1; i<= 3 ; i++){
            System.out.println(Thread.currentThread().getName() +":"+i);
        }
    }

}

//建立子線程方法二:實現Runnable 接口    用的較多,有利於資源共享
class ThreadDemo implements Runnable{

    @Override
    public void run() {
        for(int i = 1; i<= 3 ; i++){
            System.out.println(Thread.currentThread().getName() +"吃飯");
        }

    }
}

public class TestThread1 {

    public static void main(String[] args) {
//      //建立一個線程對象
//      Thread t = new Thread();
//      //啓動線程
//      t.start();

//      //建立一個子線程
//      MyThread t1 = new MyThread("t1");//新建
//      //啓動子線程,必須用start,而且只能啓動一次
//      t1.start();//就緒

        //不是線程對象
        ThreadDemo demo = new ThreadDemo();
        //                     綁定ThreadDemo類對象
        //Thread zhangsan = new Thread(demo);
        Thread zhangsan = new Thread(demo,"張三");
        Thread lisi = new Thread(demo,"李四");

        //設置優先級
        /*  lisi.setPriority(10);
        zhangsan.setPriority(1);*/
        //最低,普通,最高        比直接賦予數字好一些
        //1   5   10
        zhangsan.setPriority(Thread.MAX_PRIORITY);
        zhangsan.setPriority(Thread.MIN_PRIORITY);
        zhangsan.setPriority(Thread.NORM_PRIORITY);

        //啓動線程
        zhangsan.start();
        lisi.start();

        //但願主線程最後結束方法一
    /*  try {
            Thread.sleep(1000);//等1000毫秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        ////但願主線程最後結束方法二:判斷子線程是否運行
/*      if(zhangsan.isAlive() || lisi.isAlive()){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }*/

    //但願主線程最後結束方法三:讓子線程都執行完才能恢復主線程
        try {
            zhangsan.join();
            lisi.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("主線程結束");

    }

}
線程優先級

1 – 10

10最高

  • 理論上,優先級高的線程比優先級低的線程得到更 多的CPU時間
  • 實際上,線程得到的CPU時間一般由包括優先級在 內的==多個因素==決定
  • 理論上,等優先級線程有同等的權利使用CPU

/** 建立子線程 */

//建立子線程方法一:繼承自Thread類  
class MyThread extends Thread{
    MyThread(String name){
        super(name);
    }

    //子線程的任務功能在run中
    @Override
    public void run() {
        for(int i = 1; i<= 3 ; i++){
            System.out.println(Thread.currentThread().getName() +":"+i);
        }
    }

}

//建立子線程方法二:實現Runnable 接口    用的較多,有利於資源共享
class ThreadDemo implements Runnable{

    @Override
    public void run() {
        for(int i = 1; i<= 3 ; i++){
            System.out.println(Thread.currentThread().getName() +"吃飯");
        }

    }
}

public class TestThread1 {

    public static void main(String[] args) {
//      //建立一個線程對象
//      Thread t = new Thread();
//      //啓動線程
//      t.start();

//      //建立一個子線程
//      MyThread t1 = new MyThread("t1");//新建
//      //啓動子線程,必須用start,而且只能啓動一次
//      t1.start();//就緒

        //不是線程對象
        ThreadDemo demo = new ThreadDemo();
        //                     綁定ThreadDemo類對象
        //Thread zhangsan = new Thread(demo);
        Thread zhangsan = new Thread(demo,"張三");
        Thread lisi = new Thread(demo,"李四");

        //設置優先級
        /*  lisi.setPriority(10);
        zhangsan.setPriority(1);*/
        //最低,普通,最高        比直接賦予數字好一些
        //1   5   10
        zhangsan.setPriority(Thread.MAX_PRIORITY);
        zhangsan.setPriority(Thread.MIN_PRIORITY);
        zhangsan.setPriority(Thread.NORM_PRIORITY);

        //啓動線程
        zhangsan.start();
        lisi.start();

        //但願主線程最後結束方法一
    /*  try {
            Thread.sleep(1000);//等1000毫秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        ////但願主線程最後結束方法二:判斷子線程是否運行
/*      if(zhangsan.isAlive() || lisi.isAlive()){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }*/

    ////但願主線程最後結束方法三:讓子線程都執行完才能恢復主線程
        try {
            zhangsan.join();
            lisi.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("主線程結束");

    }

}
線程其它方法interrupt()線程中斷 :sleep()和join()

**問題:**java線程何時會引起InterruptedException ?

前提:當前線程處於sleep或者join時,被其餘線程中斷了,那麼當前線程會進行異常處理

class ThreadDemo1 implements Runnable{

    @Override

    public void run() {

        for(int i = 1 ; i <=5 ; i++){

            System.out.println(Thread.currentThread().getName()+","+i);

            if(i == 3){

                try {

                    //Thread.sleep(1000);

                    Thread.currentThread().join();

                } catch (InterruptedException e) {

                    System.out.println("進入異常處理了");

                //  e.printStackTrace();

                }

            }

        }

    }

}

public class TestThreadInterrupt {

    public static void main(String[] args) {

        ThreadDemo1 demo1 = new ThreadDemo1();

        Thread t1 = new Thread(demo1);

        t1.start();

        //主線程調用了子線程t1的interrupt方法,子線程t1被中斷進入異常處理

        t1.interrupt();

    }

}

yield() 線程讓步 (瞭解便可,如今基本不用):

Thread.yield():不能徹底保證線程讓步

class ThreadDemo1 implements Runnable{

    @Override

    public void run() {

        for(int i = 1 ; i <=5 ; i++){

            System.out.println(Thread.currentThread().getName()+","+i);

            if(i == 3){

                try {

                    //Thread.sleep(1000);

                    Thread.currentThread().join();

                } catch (InterruptedException e) {

                    System.out.println("進入異常處理了");

                //  e.printStackTrace();

                }

            }

        }

    }

}

public class TestThreadInterrupt {

    public static void main(String[] args) {

        ThreadDemo1 demo1 = new ThreadDemo1();

        Thread t1 = new Thread(demo1);

        t1.start();

        //主線程調用了子線程t1的iterrupt方法,子線程t1被中斷進入異常處理

        t1.interrupt();

    }

}

線程的同步什麼是同步

某一時刻 此資源 只能被一個線程獨佔。
線程同步的真實意思和字面意思剛好相反。線程同步的真實意思,實際上是「排隊」:幾個線程之間要排隊,一個一個對共享資源進行操做,而不是同時進行操做。

爲何使用同步

當兩個或兩個以上的線程須要共享資源,他們須要某種方法來肯定資源在某一時刻僅被一個線程佔用,達到此目的的過程叫作同步。(某一時刻資源只能被一個線程獨佔)

使用同步

  • 同步代碼塊
    咱們能夠將對某個方法的調用放入一個synchronized塊內

synchronized(對象){

同步塊;

}

同步方法,鎖的是對象 this
synchronized  方法{   }
1
/**同步示例代碼*/
class Bank implements Runnable{
    int money = 0;
    //存錢
    //同步方法
    synchronized public void setMoney(){
        money += 100;//存100
        System.out.println(Thread.currentThread().getName() + "存了100,餘額:" +money);
    }
    @Override
    public void run() {
        for(int i = 0 ; i < 3 ; i++){
            //同步鎖
            //同步塊
/*          synchronized(this){
            setMoney();
            }*/
            setMoney();
        }

    }

}
public class TestBank {

    public static void main(String[] args) {
        Bank bank = new Bank();
        Thread zhangsan = new Thread(bank,"zhangsan");
        Thread lisi = new Thread(bank,"lisi");
        zhangsan.start();
        lisi.start();
    }

}
Lock優點

能夠顯示加鎖,釋放鎖

得到鎖:

當一個線程 訪問此對象的 同步塊 或 同步方法的時候,
申請同步鎖,申請成功了,就得到了鎖。在執行 同步塊
和 同步方法的過程當中,其它線程 進入 線程鎖定池中處於
阻塞狀態。只有 當前執行鎖的線程 釋放了鎖 其它線程
纔有 機會 得到CPU的調用執行。

釋放鎖:

1.同步方法或同步塊中的 代碼正常執行完了,就釋放了;
2. 出現了未處理的 異常Exception和
Error時 ,釋放鎖;
3。 break,return語句,會結束方法或
代碼塊,那麼會釋放鎖。
4. 執行了 wait()會釋放鎖。

語法:
try{  
    加鎖lock

}finally{   
    釋放unLock

}

lock做用

能夠顯示加鎖和釋放鎖
提供了更多功能
死鎖

每一個對象只有一個鎖(lock)不之相關聯
實現同步是要很大的系統開銷做爲代價的,甚至可 能形成死鎖,因此儘可能避免無謂的同步控制
/**死鎖示例代碼 */
class Zhangsan{
    public void say(){
        System.out.println("你給我書,我就給你畫");
    }
    public void get(){
        System.out.println("張三得到了書");
    }
}

class Lisi{
    public void say(){
        System.out.println("你給我畫,我就給你書");
    }
    public void get(){
        System.out.println("李四得到了畫");
    }
}
class LockDemo implements Runnable{
    static Zhangsan zhangsan = new Zhangsan();
    static Lisi lisi = new Lisi();
    boolean tag ;

    @Override
    public void run() {
        if(tag == true){//張三
            synchronized(zhangsan){
            zhangsan.say();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            synchronized(lisi){
                zhangsan.get();
            }
            }
        }else{//李四
            synchronized(lisi){
                lisi.say();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                synchronized(zhangsan){
                    lisi.get();
                }
            }
        }

    }

}
public class Testlock {

    public static void main(String[] args) {
        LockDemo demo1 = new LockDemo();
        demo1.tag = true;
        LockDemo demo2 = new LockDemo();
        demo2.tag = false;
        Thread t1 = new Thread(demo1);
        Thread t2 = new Thread(demo2);
        t1.start();
        t2.start();
    }

}

wait()和sleep的區別:

區別:
時間參數
wait()能夠可定時間也能夠丌指定; sleep()必須指定時間;
同步狀態
sleep()釋放執行權,不釋放鎖 ;wait釋放執行權,釋放鎖
class Show implements Runnable{
    int i = 10 ;
    @Override
    synchronized public void run() {
        for(; i >= 0 ; i--){

            if(i == 5  && Thread.currentThread().getName().equals("t1:")){
                try {
                    //Thread.sleep(100000);
                    wait(1000);
                    System.out.println("我醒了");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+i);
        }   

    }

}

public class Exercise1 {

    public static void main(String[] args) {
        Show sh = new Show();
        Thread t1 = new Thread(sh,"t1:");
        Thread t2 = new Thread(sh,"t2:");
        t1.start();
        t2.start();

    }

}
包子鋪實例理解wait()、notify()

package day26;
class QingFeng {
    private int count;//包子數量
    private boolean tag = false;//true ->有包子,false->沒包子

    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }

    //生產包子
    synchronized public void put(int count){
        //有包子,休息
        if(tag == true){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //沒有包子 false
        this.count = count;
        System.out.println("生產了" +this.count);
        tag = true;
        notify();//喚醒銷售
    }
    //銷售包子
    synchronized public void get(){
        //沒包子可賣,休息一會
        if(tag == false){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 有包子true
        System.out.println("賣了" +this.count);
        tag = false;//賣完了
        notify();//喚醒廚師
    }

}
//生產
class Producer implements Runnable{
    QingFeng qingfeng;

    public Producer(QingFeng qingfeng) {
        super();
        this.qingfeng = qingfeng;
    }

    public Producer() {
        super();
    }

    @Override
    public void run() {
        //生產
        for(int i = 1 ; i <=5 ; i++){
            qingfeng.put(i);
        }
    }

}

//銷售
class Consumer implements Runnable{
    QingFeng qingfeng;

    public Consumer() {
        super();
    }

    public Consumer(QingFeng qingfeng) {
        super();
        this.qingfeng = qingfeng;
    }

    @Override
    public void run() {
        for(int i = 1 ; i <= 5 ; i++){
            qingfeng.get();
        }
    }

}

public class Exercise2 {

    public static void main(String[] args) {
        QingFeng qingfeng = new QingFeng();
        Producer pro = new Producer(qingfeng);
        Consumer con = new Consumer(qingfeng) ;
        Thread t1 = new Thread(pro);
        Thread t2 = new Thread(con);
        t1.start();
        t2.start();

    }

}

相關文章
相關標籤/搜索