多線程經典案例

售票服務java

public class Station extends Thread {
 
        // 經過構造方法給線程名字賦值
        public Station(String name) {
             super(name);// 給線程名字賦值
        }
         
        // 爲了保持票數的一致,票數要靜態
        static int tick = 20;
         
        // 建立一個靜態鑰匙
        static Object ob = new Object();//值是任意的
         
        // 重寫run方法,實現買票操做
        @Override
        public void run() {
            while (tick > 0) {
                synchronized (ob) {// 這個很重要,必須使用一個鎖,
                    // 進去的人會把鑰匙拿在手上,出來後才把鑰匙拿讓出來
                    if (tick > 0) {
                        System.out.println(getName() + "賣出了第" + tick + "張票");
                        tick--;
                    } else {
                        System.out.println("票賣完了");
                    }
                }
                try {
                     sleep(1000);//休息一秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
             
            }
    }
 
}
public class MainClass {
    /**
     * java多線程同步鎖的使用
     * 示例:三個售票窗口同時出售10張票
     * */
    public static void main(String[] args) {
        //實例化站臺對象,併爲每個站臺取名字
         Station station1=new Station("窗口1");
         Station station2=new Station("窗口2");
         Station station3=new Station("窗口3");
     
        // 讓每個站臺對象各自開始工做
         station1.start();
         station2.start();
         station3.start();
     
    }
 
}

銀行取款數組

public class Bank {
 
    // 假設一個帳戶有1000塊錢
    static int money = 1000;
     
    // 櫃檯Counter取錢的方法
    public void Counter(int money) {// 參數是每次取走的錢
        Bank.money -= money;//取錢後總數減小
        System.out.println("A取走了" + money + "還剩下" + (Bank.money));
    }
     
    // ATM取錢的方法
    public void ATM(int money) {// 參數是每次取走的錢
        Bank.money -= money;//取錢後總數減小
        System.out.println("B取走了" + money + "還剩下" + (Bank.money));
    }
     
}
public class PersonA extends Thread {
    // 建立銀行對象
    Bank bank;
     
    // 經過構造器傳入銀行對象,確保兩我的進入的是一個銀行
    public PersonA(Bank bank) {
         this.bank = bank;
    }
    
    //重寫run方法,在裏面實現使用櫃檯取錢
    @Override
        public void run() {
            while (Bank.money >= 100) {
                bank.Counter(100);// 每次取100塊
            try {
                sleep(100);// 取完休息0.1秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class PersonB extends Thread {
    // 建立銀行對象
    Bank bank;
     
    // 經過構造器傳入銀行對象,確保兩我的進入的是一個銀行
    public PersonB(Bank bank) {
        this.bank = bank;
    }
     
    // 重寫run方法,在裏面實現使用櫃檯取錢
    @Override
    public void run() {
        while (Bank.money >= 200) {
            bank.ATM(200);// 每次取200塊
            try {
                sleep(100);// 取完休息0.1秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
         
    }
}
public class MainClass {
    /**
     * 兩我的AB經過一個帳戶A在櫃檯取錢和B在ATM機取錢
     * */
    public static void main(String[] args) {
        // 實力化一個銀行對象
        Bank bank = new Bank();
        // 實例化兩我的,傳入同一個銀行的對象
        PersonA pA = new PersonA(bank);
        PersonB pB = new PersonB(bank);
        // 兩我的開始取錢
        pA.start();
        pB.start();
         
    }
 
}

龜兔賽跑多線程

public abstract class Animal extends Thread{

    public double length=20;//比賽的長度
    
    public abstract void runing();//抽象方法須要子類實現
    
    //在父類重寫run方法,在子類只要重寫running方法就能夠了
    @Override
    public void run() {
        super.run();
        while (length>0) {
             runing();
        }
    }
    
    //在須要回調數據的地方(兩個子類須要),聲明一個接口
    public static interface Calltoback{
        public void win();
    }
    
    //2.建立接口對象
    public Calltoback calltoback;
    
}
public class Rabbit extends Animal {
     
    public Rabbit() {
        setName("兔子");// Thread的方法,給線程賦值名字
    }
     
    // 重寫running方法,編寫兔子的奔跑操做
    @Override
    public void runing() {
        // 跑的距離
        double dis = 0.5;
        length -= dis;//跑完後距離減小
        if (length <= 0) {
            length = 0;
            System.out.println("兔子得到了勝利");
            //給回調對象賦值,讓烏龜不要再跑了
            if (calltoback != null) {
                calltoback.win();
            }
        }
        System.out.println("兔子跑了" + dis + "米,距離終點還有" + (int)length + "米");
         
        if (length % 2 == 0) {// 兩米休息一次
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class Tortoise extends Animal {
     
    public Tortoise() {
        setName("烏龜");// Thread的方法,給線程賦值名字
    }
     
    // 重寫running方法,編寫烏龜的奔跑操做
    @Override
    public void runing() {
        // 跑的距離
        double dis = 0.1;
        length -= dis;
        if (length <= 0) {
            length = 0;
            System.out.println("烏龜得到了勝利");
            // 讓兔子不要在跑了
            if (calltoback != null) {
                calltoback.win();
            }
        }
        System.out.println("烏龜跑了" + dis + "米,距離終點還有" + (int) length + "米");
        try {
            sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class LetOneStop implements Calltoback {

    // 動物對象
    Animal an;
    
    // 獲取動物對象,能夠傳入兔子或烏龜的實例
    public LetOneStop(Animal an) {
        this.an = an;
    }
    
    //讓動物的線程中止
    @Override
    public void win() {
        // 線程中止
        an.stop();
    }
     
}
public class MainClass {
    /**
     * 龜兔賽跑:20米      
     * */
    public static void main(String[] args) {
        //實例化烏龜和兔子
        Tortoise tortoise = new Tortoise();
        Rabbit rabbit = new Rabbit();
        //回調方法的使用,誰先調用calltoback方法,另外一個就不跑了
        LetOneStop letOneStop1 = new LetOneStop(tortoise);
        rabbit.calltoback = letOneStop1;//讓兔子的回調方法裏面存在烏龜對象的值,能夠把烏龜stop
        LetOneStop letOneStop2 = new LetOneStop(rabbit);
        tortoise.calltoback = letOneStop2;//讓烏龜的回調方法裏面存在兔子對象的值,能夠把兔子stop
        //開始跑
        tortoise.start();
        rabbit.start();
     
    }
 
}

生產者消費者模式app

public class Food {
    String name="";
    //經過構造方法傳入食物的名字
    public Food(String name) {
        this.name=name;
    }
    //get、set 方法
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
public class KFC {

    //食物的種類
    String[] names = { "薯條", "燒板", "雞翅", "可樂" };
    
    //生產的最大值,到達後能夠休息
    static final int Max = 20;
    
    //存放食物的集合
    List foods = new ArrayList();
     
    // 生產食物的方法
    public void prod(int index) {
        synchronized (this) {
            // 若是食物數量大於20
            while (foods.size() > Max) {
                System.out.println("食材夠了");
                this.notifyAll();//這個喚醒是針對生產者和消費者,有all
                try {
                    String name=Thread.currentThread().getName();
                    this.wait();//這個喚醒是針對生產者,沒有all
                    System.out.println("生產者:"+name);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
             
            // 開始生產食物食物//有一點要注意的
            System.out.println("開始生產食物");
            for (int i = 0; i < index; i++) {
                Food food = new Food(names[(int) (Math.random() * 4)]);
                foods.add(food);
                System.out.println("生產了" + food.getName() + foods.size());
            }
        }
    }
public void consu(int index) { 
        synchronized (this) {
            while (foods.size() < index) {
                System.out.println("食材不夠了");
                this.notifyAll();//這個喚醒是針對生產者和消費者,有all
                try {
                    String name=Thread.currentThread().getName();
                    this.wait();//這個喚醒是針對消費者,沒有all
                    System.out.println("消費者:"+name);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 足夠消費
            System.out.println("開始消費");
            for (int i = 0; i < index; i++) {
                Food food = foods.remove(foods.size() - 1);
                System.out.println("消費了一個" + food.getName() + foods.size());
            }
        }
    }
}
public class Customers extends Thread{
    KFC kfc;
    //KFC要傳入,保證每個服務員和用戶在同一個KFC對象內
    public Customers(KFC kfc) {
        this.kfc=kfc;
    }
    @Override
    public void run() {
        int size=(int)(Math.random()*5);//每次要消費的食物的數量
        while (true) {
            kfc.consu(size);//在消費的方法裏面傳入參數
        }
     
    }
}
public class Waiter extends Thread{
    KFC kfc;
    //KFC要傳入,保證每個服務員和用戶在同一個KFC對象內
    public Waiter(KFC kfc) {
        this.kfc=kfc;
    }
    @Override
    public void run() {
        int size=(int)(Math.random()*5)+5;//每次生產的數量
        while (true) {
            kfc.prod(size);//傳入每次生產的數量
        }
     
    }
}
public class MainClass {
    /**
     * 生產者消費者模式
     *
     * */
    public static void main(String[] args) {
    
        // 只實例化一個KFC對象,保證每個服務員和用戶在同一個KFC對象內
        KFC kfc = new KFC();
        
        //實例化4個客戶對象
        Customers c1 = new Customers(kfc);
        Customers c2 = new Customers(kfc);
        Customers c3 = new Customers(kfc);
        Customers c4 = new Customers(kfc);
        
        //實例化3個服務員對象
        Waiter waiter1 = new Waiter(kfc);
        Waiter waiter2 = new Waiter(kfc);
        Waiter waiter3 = new Waiter(kfc);
        
        //讓全部的對象的線程都開始工做
        waiter1.start();
        waiter2.start();
        waiter3.start();
        c1.start();
        c2.start();
        c3.start();
        c4.start();
    }
     
}

 設計四個線程對象對同一個數據進行操做dom

public class ThreadAddSub extends Thread {
    //判斷要進行的操做
    boolean operate = true;
    //要操做的數
    static int sum = 0;
     
    // 把操做運算經過構造方法傳進來
    public ThreadAddSub(boolean operate) {
        super();
        this.operate = operate;
    }
     
    @Override
    public void run() {
        super.run();
        while (true) {
            if (operate) {
                sum+=5;
                System.out.println("加後,sum="+sum);
            } else {
                sum-=4;
                System.out.println("減後,sum="+sum);
            }
            try {
                sleep(500);// 睡眠0.5秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
     
    }
}
public class MainClass {
    /**
     * (線程同步)
     * */
    public static void main(String[] args) {
    
        //建立一個存放ThreadAddSub對象的數組
        ThreadAddSub[] tSub=new ThreadAddSub[4];
        for (int i = 0; i < tSub.length; i++) {
        
        //把實例化ThreadAddSub對象賦值到數組內
        //第一三個是true,二四個是false
        tSub[i]=new ThreadAddSub(i%2==0?true:false);
        
        //讓線程開始工做
        tSub[i].start();
        }
     
    }
 
}

電影院選座ide

public class HappyCinema2 {
    public static void main(String[] args) {
        Cinema2 c = new Cinema2(Arrays.asList(1,2,3,4,5), "happy cinema");
        new Thread(new Customer2(c,Arrays.asList(1,2))).start();
        new Thread(new Customer2(c,Arrays.asList(3,5))).start();
    }
}

class Cinema2{
    private List<Integer> available;
    private String name;

    Cinema2(List<Integer> available, String name){
        this.available = available;
        this.name = name;
    }

    boolean bookTickets(List<Integer> seats) {
        System.out.println("可用位置:" + available);
        List<Integer> copy = new ArrayList<>(available);
        copy.removeAll(seats);
        if (copy.size() + seats.size() == available.size()) {
            available = copy;
            return true;
        }
        return false;
    }
}

class Customer2 implements Runnable{
    private final Cinema2 cinema;
    private List<Integer> seats;

    Customer2(Cinema2 cinema, List<Integer> seats) {
        this.cinema = cinema;
        this.seats = seats;
    }

    @Override
    public void run() {
        synchronized (cinema) {
            boolean flag = cinema.bookTickets(seats);
            if (flag) {
                System.out.println("出票成功" + seats + "個位置");
            } else {
                System.out.println("出票失敗,位置不夠");
            }
        }
    }
}
相關文章
相關標籤/搜索