1. 程式人生 > >java學習筆記(20-多執行緒)

java學習筆記(20-多執行緒)

1. Thread類

1.1 繼承實現

package com.daigua20;

public class ThreadDemo {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        // 修改執行緒名字
        t1.setName("呆瓜");
        // 啟動任務
        t1.start();

        MyThread t2 = new MyThread();
        // 修改執行緒名字
        t2.setName("豬娃");
        // 啟動任務
        t2.start();

    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(getName() + ":" + i);
        }
    }
}

1.2 Runnable介面實現

package com.daigua20;

public class ThreadDemo2 {
    public static void main(String[] args) {
        // 例項出Runnable介面子類的物件
        MyThread2 r1 = new MyThread2(10);
        MyThread2 r2 = new MyThread2(10);

        // 用Runnable子類構造Thread類的例項
        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);

        // start方法啟動任務
        t1.start();
        t2.start();
    }
}

// 定義Runnable介面的子類,重寫run方法
class MyThread2 implements Runnable {
    int num;

    public MyThread2(int num) {
        this.num = num;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i + num);
        }
    }
}

2.執行緒安全

2.1 資源共享導致的問題

package com.daigua20;


public class ThreadDemo3 {
    public static void main(String[] args) {
        TicketThread r1 = new TicketThread();

        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r1);
        Thread t3 = new Thread(r1);

        t1.start();
        t2.start();
        t3.start();
    }
}


class TicketThread implements Runnable {
    // 車票數量一百張
    int tickets = 100;

    @Override
    public void run() {
        while (true) {
            if (tickets > 0) {
                try {
                    Thread.sleep(100);
                    tickets -= 1;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":" + tickets);
            }
        }
    }
}

2.2解決方法

2.2.1 使用同步程式碼塊

格式:
  synchronized(鎖物件){
      //需要同步的程式碼
}
package com.daigua20;
/*
 *  synchronized:同步(鎖),可以修飾程式碼塊和方法,被修飾的程式碼塊和方法一旦被某個執行緒訪問,則直接鎖住,其他的執行緒將無法訪問
 *
 * 同步程式碼塊:
 *          synchronized(鎖物件){
 *
 *          }
 *
 * 注意:鎖物件需要被所有的執行緒所共享
 *
 *
 * 同步:安全性高,效率低
 * 非同步:效率高,但是安全性低
 *
 */

public class ThreadDemo4 {
    public static void main(String[] args) {
        TicketThread2 r1 = new TicketThread2();
        
        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r1);
        Thread t3 = new Thread(r1);
        t1.setName("視窗1");
        t2.setName("視窗2");
        t3.setName("視窗3");

        t1.start();
        t2.start();
        t3.start();
    }
}


class TicketThread2 implements Runnable {
    // 車票數量一百張
    int tickets = 100;
    Object obj = new Object();

    @Override
    public void run() {
        while (true) {
            synchronized (obj) {
                if (tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":" + tickets--);
                }
            }
        }
    }
}

2.2.2 使用同步方法

 格式:
  修飾符 synchronized 返回值 方法名(){

}
package com.daigua20;
/*
 * 同步方法:使用關鍵字synchronized修飾的方法,一旦被一個執行緒訪問,則整個方法全部鎖住,其他執行緒則無法訪問
 *
 * synchronized
 * 注意:
 *      非靜態同步方法的鎖物件是this
 *      靜態的同步方法的鎖物件是當前類的位元組碼物件
 */
public class ThreadDemo5 {
    public static void main(String[] args) {
        TicketThread3 tt = new TicketThread3();

        Thread t1 = new Thread(tt);
        Thread t2 = new Thread(tt);
        Thread t3 = new Thread(tt);

        t1.setName("視窗1");
        t2.setName("視窗2");
        t3.setName("視窗3");

        t3.start();
        t2.start();
        t1.start();
    }
}


class TicketThread3 implements Runnable {
    // 車票數量一百張
    static int  tickets = 100;
//    Object obj = new Object();

    @Override
    public void run() {
        while (true) {
                if (tickets > 0) {
//                    method();
                    method2();
            }
        }
    }

    private synchronized void method(){
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + ":" + tickets--);
    }

    private static synchronized void method2(){
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + ":" + tickets--);
    }

}