1. 程式人生 > >執行緒的學習1(常見簡單方法)

執行緒的學習1(常見簡單方法)

程序&執行緒

  • 程序:執行中的應用程式稱為程序,擁有系統資源(cpu,記憶體)
  • 執行緒:程序中的程式片段,一個程序中可以有多個程式片段。本身不單獨擁有資源(共享所在程序的資源)

並行&併發

  • 並行:兩個任務同時進行。真正意義上的同時進行,可以理解為同時使用兩臺電腦執行兩個任務。在一臺電腦上需要多核cpu
  • 併發:兩個任務都請求執行,但是處理器同時只能接受一個任務執行的請求。
  • 一個程序裡的執行緒都是併發進行的,多個執行緒之間相互搶奪系統資源。由於時間間隔很短給人的感覺就好像在同時進行。

建立執行緒的兩種方式

  1. 建立類繼承Thread類,然後重寫run方法。將該執行緒要實現的事務寫在run方法中,建立執行緒物件
class MyThread extends Thread{
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        for (int i = 0; i < 1000; i++) {
            System.out.println("1執行緒"+i);
        }
    }
}
/*
 * 呼叫執行緒:使用Thread類裡的start()方法來啟動執行緒
 * 
 */
 public static void
main(String[] args) { MyThread myThread =new MyThread(); myThread.start(); }

2 . 建立類實現Runnable介面

class RunnableImpl1 implements Runnable{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 1000; i++) {
            System.out.println(Thread.currentThread().getName()+"2執行緒"
+i); } } } /* - 呼叫執行緒:新建Thread物件並傳入RunnableImpl1 類物件 - */ public static void main(String[] args) { RunnableImpl1 runnableImpl1 =new RunnableImpl1 (); new Thread(runnableImpl1).start(); }

兩種方法的區別
a.繼承Thread類

  • 優點 :繼承Thread類建立執行緒,可以直接使用繼承自父類中的方法,程式碼更簡單。
  • 缺點 :java中只能單繼承,若是已經有了一個父類,就不能用這種方法。
    b.實現Runnable介面

  • 優點 :java中介面可以實現多個,在有父類的情況下仍然可以通過實現介面來建立執行緒

  • 缺點 :在呼叫執行緒的時候還得建立Thread物件,程式碼比較複雜

在實際應用中一般會選擇實現Runnable介面的方法

執行緒中常用到的一些方法

獲取當前執行緒物件

Thread.currentThread()
- 執行緒休眠
Thread.sleep() :傳入時間作為引數,時間單位為毫秒。一般使用1000*n來表示n秒時間

package com.hwadee.thread;

/**
 * 
 * 獲取當前執行緒物件
 * 設定當前執行緒名稱 獲取當前執行緒名稱
 * 執行緒休眠
 *
 */
public class Thread2 {

    public static void main(String[] args) {
        Thread.currentThread().setName("扛把子");
        System.out.println("任務開始");
        for (int i = 0; i < 10; i++) {
            System.out.println("主執行緒名字為:"+Thread.currentThread().getName()+"   執行第"+i+"次");
        }
        MyThread1 myThread =new MyThread1();
        myThread.setName("繼承Thread類建立的執行緒");
        myThread.start();
        RunnableImpl3 runnableImpl3 = new RunnableImpl3();
        new Thread(runnableImpl3).setName("二把刀");
        new Thread(runnableImpl3).start();

        System.out.println("我看個電影");

    }


}
class MyThread1 extends Thread{
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        for (int i = 0; i < 10; i++) {
            System.out.println(getName()+"1執行緒"+i);
        }
    }
}
class RunnableImpl3 implements Runnable{

    @Override
    public void run() {

        SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


        for (int i = 0; i < 10; i++) {
            if(i==5) {

                System.out.println(simpleDateFormat.format(new Date())+"先讓你睡他個十秒鐘");
                try {   
                    Thread.sleep(1000*10);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(simpleDateFormat.format(new Date())+"醒來了繼續執行");

        }else {
            System.out.println(Thread.currentThread().getName()+"執行緒"+i);
        }

    }

    }
}
//輸出結果
任務開始
主執行緒名字為:扛把子   執行第0次
主執行緒名字為:扛把子   執行第1次
主執行緒名字為:扛把子   執行第2次
主執行緒名字為:扛把子   執行第3次
主執行緒名字為:扛把子   執行第4次
主執行緒名字為:扛把子   執行第5次
主執行緒名字為:扛把子   執行第6次
主執行緒名字為:扛把子   執行第7次
主執行緒名字為:扛把子   執行第8次
主執行緒名字為:扛把子   執行第9次
繼承Thread類建立的執行緒1執行緒0
繼承Thread類建立的執行緒1執行緒1
繼承Thread類建立的執行緒1執行緒2
繼承Thread類建立的執行緒1執行緒3
繼承Thread類建立的執行緒1執行緒4
繼承Thread類建立的執行緒1執行緒5
繼承Thread類建立的執行緒1執行緒6
繼承Thread類建立的執行緒1執行緒7
繼承Thread類建立的執行緒1執行緒8
繼承Thread類建立的執行緒1執行緒9
我看個電影
Thread-2執行緒0
Thread-2執行緒1
Thread-2執行緒2
Thread-2執行緒3
Thread-2執行緒4
2018-01-29 13:42:31先讓你睡他個十秒鐘
2018-01-29 13:42:41醒來了繼續執行
Thread-2執行緒6
Thread-2執行緒7
Thread-2執行緒8
Thread-2執行緒9
  • 守護執行緒
    setDeamon():設定一個執行緒作為守護執行緒,該執行緒不會單獨執行,當其他非守護執行緒都執行結束後,自動退出
package com.hwadee.thread;

public class TestDeamon {

    public static void main(String[] args) {
        Thread4 thread4 = new Thread4();
        thread4.setName("騎士1");
        thread4.setDaemon(true);
        Thread5 thread5 = new Thread5();
        thread5.setName("騎士2");
        thread5.setDaemon(true);
        Thread6 thread6 = new Thread6();
        thread6.setName("公主");
        thread4.start();
        thread5.start();
        thread6.start();
    }
}
class Thread4 extends Thread{
    @Override
    public void run() {
        for(int i=0;i<30;i++) {
            System.out.println(getName()+"第"+i+"次");
        }
    }
}
class Thread5 extends Thread{
    @Override
    public void run() {
        for(int i=0;i<30;i++) {
            System.out.println(getName()+"第"+i+"次");
        }
    }
}
class Thread6 extends Thread{
    @Override
    public void run() {
        for(int i=0;i<5;i++) {
            System.out.println(getName()+"第"+i+"次");
        }
    }
}
  • 加入執行緒
    join():當前執行緒暫停,等待指定的執行緒執行結束後,當前執行緒再繼續,可以傳入引數表示等待指定的毫秒之後繼續
    這個方法在我理解看來與其叫加入執行緒不如叫執行緒插隊更好理解。
package com.hwadee.thread;

public class TestJoin {

    public static void main(String[] args) {
        Thread t1=new Thread(){
            public void run() {
                setName("執行緒1");
                for (int i = 0; i < 50; i++) {
                    System.out.println(getName()+"執行第"+i+"次");
                }
            }
        };
        Thread t2=new Thread(){
            public void run() {
                setName("執行緒2");
                for (int i = 0; i < 10; i++) {
                    if(i==3) {
                        try {
                            System.out.println("-------------執行緒1插個隊-----");
                            t1.join();
//                          t1.join(1000*5);

                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }

                    }
                    System.out.println(getName()+"執行第"+i+"次");
                }
            }
        };
        t1.start();
        t2.start();
    }


}
  • 禮讓執行緒
  • yield():執行緒在執行過程中會搶奪cpu資源,導致不斷的相互切換,可以呼叫yield()方法讓出cpu
package com.hwadee.thread;

public class TestYield {

    public static void main(String[] args) {
        new MThread1().start();
        new MThread1().start();


    }

}
class MThread1 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            if(i==2) {
                Thread.yield();

            }
            System.out.println(getName()+"執行第"+i+"次");
        }
    }
}
  • 設定執行緒優先順序
    優先順序越高的執行緒被執行緒排程器呼叫的機率就越高
    setPriority(int level):優先順序是[1-10]之間的一個整數。線上程執行中會起一定的作用,但是作用不大
package com.hwadee.thread;

public class TestPriority {

    public static void main(String[] args) {
        Thread t1=new Thread(){
            public void run() {
                setName("執行緒1");
                for (int i = 0; i < 50; i++) {
                    System.out.println(getName()+"執行第"+i+"次");
                }
            }
        };
        Thread t2=new Thread(){
            public void run() {
                setName("執行緒2");
                for (int i = 0; i < 10; i++) {
                    System.out.println(getName()+"執行第"+i+"次");
                }
            }
        };
        t1.setPriority(1);
        t2.setPriority(10);
        t1.start();
        t2.start();
    }


}
  • 執行緒鎖
    代表這個方法加鎖,相當於不管哪一個執行緒(例如執行緒A),執行到這個方法時,都要檢查有沒有其它執行緒B(或者C、 D等)正在用這個方法(或者該類的其他同步方法),有的話要等正在使用synchronized方法的執行緒B(或者C 、D)執行完這個方法後再執行此執行緒A,沒有的話,鎖定呼叫者,然後直接執行。

synchronized(Object){
程式碼塊
}

package com.hwadee.thread;

public class TestSynchronized {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Test11 test=new Test11();

        Thread t1=new Thread(test);
        t1.setName("1號視窗");
        Thread t2=new Thread(test);
        t2.setName("2號視窗");
        Thread t3=new Thread(test);
        t3.setName("3號視窗");
        t1.start();
        t2.start();
        t3.start();
    }

}
class Test11 implements Runnable{
    int t=500;
    Object o=new Object();
    @Override
    public void run() {
        while(t>0) {
        synchronized (o) {

            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"正在售出第"+t--+"張票");
        } 
        }
    }
}