八個經典的java多線程編程題目

1、要求線程a執行完纔開始線程b, 線程b執行完纔開始線程

package com.example.javatest.theardTest.MultiThreadAlgorithm;

/**
 * 要求線程a執行完纔開始線程b, 線程b執行完纔開始線程
 *
 * join()解釋:https://blog.csdn.net/qq_18505715/article/details/79795728
 *
 * wait()  和  notify()  解釋:https://blog.csdn.net/chaozhi_guo/article/details/50249177
 *
 * join()的作用:主要作用是同步,它可以使得線程之間的並行執行變爲串行執行。在A線程中調用了B線程的join()方法時,表示只有當B線程執行完畢時,A線程才能繼續執行。
 *
 * public void joinDemo(){
 *    //....
 *    Thread t=new Thread(payService);
 *    t.start();
 *    //....
 *    //其他業務邏輯處理,不需要確定t線程是否執行完
 *    insertData();
 *    //後續的處理,需要依賴t線程的執行結果,可以在這裏調用join方法等待t線程執行結束
 *    t.join();
 * }
 *
 */
public class T1T2T3 {

    public static class PrintThread extends Thread{

        PrintThread(String name){
            super(name);
        }

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

    public static void main(String[] args){

        PrintThread t1 = new PrintThread("a");
        PrintThread t2 = new PrintThread("b");
        PrintThread t3 = new PrintThread("c");

        try {

            t1.start();
            t1.join();

            t2.start();
            t2.join();

            t3.start();
            t3.join();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }


    }

}

/**
 * 我對於join方法的理解:
 *
 *    join() 的源碼:
 *    public final void join(long millis) throws InterruptedException {
 *         synchronized(lock) {
 *         ...
 *
 *           while (isAlive()) {
 *              lock.wait(0);
 *           }
 *        ...
 *         }
 *    }
 *
 *    其實就是main()線程調用join()後,synchronized(lock)語句塊,獲得lock的鎖,
 *
 *    然後判斷如果t1線程isAlive(), 就一直lock.wait(), 讓自己(main()線程)阻塞住,
 *
 *    直到t1線程 !isAlive 後纔不wait, 等待着被notify(), 然後t1 die後會調用lock.notifyAll()。
 *
 *
 *    注意:這裏lock.wait(0)雖然在t1.join()內,但是join()內的代碼不是運行在t1線程中,而是運行在main()線程中,
 *          t1線程中運行的是其run()方法內的代碼。
 *
 */

2、兩個線程輪流打印數字,一直到100

package com.example.javatest.theardTest.MultiThreadAlgorithm;

/**
 * 兩個線程輪流打印數字,一直到100
 * 
 * Java的wait()、notify()學習:
 * https://blog.csdn.net/boling_cavalry/article/details/77995069
 */
public class TakeTurnsPrint {

    public static class TakeTurns {

        private static boolean flag = true;

        private static int count = 0;

        public synchronized void print1() {
            for (int i = 1; i <= 50; i++) {
                while (!flag) {
                    try {
                        System.out.println("print1: wait before");
                        wait();
                        System.out.println("print1: wait after");
                    } catch (InterruptedException e) {
                    }
                }

                System.out.println("print1: " + ++count);
                flag = !flag;
                notifyAll();
            }
        }

        public synchronized void print2() {
            for (int i = 1; i <= 50; i++) {
                while (flag) {
                    try {
                        System.out.println("print2: wait before");
                        wait();
                        System.out.println("print2: wait after");
                    } catch (InterruptedException e) {
                    }
                }

                System.out.println("print2: " + ++count);
                flag = !flag;
                notifyAll();
            }
        }
    }

    public static void main(String[] args){

        TakeTurns takeTurns = new TakeTurns();

        new Thread(new Runnable() {
            @Override
            public void run() {
                takeTurns.print1();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                takeTurns.print2();
            }
        }).start();

    }

}

3、寫兩個線程,一個線程打印1~ 52,另一個線程打印A~Z,打印順序是12A34B…5152Z

package com.example.javatest.theardTest.MultiThreadAlgorithm;

/**
 * 兩線程,一個打印數字從1到52,另一個打印字母從A到Z,輸出:12A34B56C...5152Z
 */
public class TakeTurnsPrint2 {
    private boolean flag;
    private int count;

    public synchronized void printNum() {
        for (int i = 0; i < 26; i++) {
                while (flag) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                flag = !flag;
                System.out.print(++count);
                System.out.print(++count);
                notify();
        }
    }

    public synchronized void printLetter() {
        for (int i = 0; i < 26; i++) {
                while (!flag) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                flag = !flag;
                System.out.print((char) (65 + i));
                notify();
        }
    }

    public static void main(String[] args) {

        TakeTurnsPrint2 turnsPrint2 = new TakeTurnsPrint2();

        new Thread(new Runnable() {
            @Override
            public void run() {
                turnsPrint2.printNum();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                turnsPrint2.printLetter();
            }
        }).start();
    }
}

4、編寫一個程序,啓動三個線程,三個線程的ID分別是A,B,C;,每個線程將自己的ID值在屏幕上打印5遍,打印順序是ABCABC…

package com.example.javatest.theardTest.MultiThreadAlgorithm;

/**
 * 編寫一個程序,啓動三個線程,三個線程的ID分別是A,B,C;,每個線程將自己的ID值在屏幕上打印5遍,打印順序是ABCABC...
 */
public class ABCABCABC {

    private int flag = 0;

    public synchronized void printA() {
        for(int i = 0; i < 5; i++) {
            while (flag != 0) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            flag = 1;
            System.out.print("A");
            notifyAll();
        }
    }

    public synchronized void printB() {
        for(int i = 0; i < 5; i++) {
            while (flag != 1) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            flag = 2;
            System.out.print("B");
            notifyAll();
        }
    }

    public synchronized void printC() {
        for(int i = 0; i < 5; i++) {
            while (flag != 2) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            flag = 0;
            System.out.print("C");
            notifyAll();
        }
    }

    public static void main(String[] args) {

        ABCABCABC abcabcabc = new ABCABCABC();

        new Thread(new Runnable() {
            @Override
            public void run() {
                abcabcabc.printA();
            }
        }).start();


        new Thread(new Runnable() {
            @Override
            public void run() {
                abcabcabc.printB();
            }
        }).start();


        new Thread(new Runnable() {
            @Override
            public void run() {
                abcabcabc.printC();
            }
        }).start();
    }
}

5、編寫10個線程,第一個線程從1加到10,第二個線程從11加20…第十個線程從91加到100,最後再把10個線程結果相加。

/**
 * 編寫10個線程,第一個線程從1加到10,第二個線程從11加20…第十個線程從91加到100,最後再把10個線程結果相加
 */
public class TenThreadSum {

    public static class SumThread extends Thread{

        int forct = 0;  int sum = 0;

        SumThread(int forct){
            this.forct = forct;
        }

        @Override
        public void run() {
            for(int i = 1; i <= 10; i++){
                sum += i + forct * 10;
            }
            System.out.println(getName() + "  " + sum);
        }
    }

    public static void main(String[] args) {

        int result = 0;

        for(int i = 0; i < 10; i++){
            SumThread sumThread = new SumThread(i);
            sumThread.start();
            try {
                sumThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            result = result + sumThread.sum;
        }
        System.out.println("result   " + result);
    }
}

6 、三個窗口同時賣票

/**
 * 三個窗口同時賣票
 */

/**
 * 票
 */
class Ticket {
    private int count = 1;
    public void sale() {
        while (true) {
            synchronized (this) {
                if (count > 200) {
                    System.out.println("票已經賣完啦");
                    break;
                } else {
                    System.out.println(Thread.currentThread().getName() + "賣的第 " + count++ + " 張票");
                }
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

/**
 * 售票窗口
 */
class SaleWindows extends Thread {
    
    private Ticket ticket;

    public SaleWindows(String name, Ticket ticket) {
        super(name);
        this.ticket = ticket;
    }

    @Override
    public void run() {
        super.run();
        ticket.sale();
    }
}

public class TicketDemo {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();

        SaleWindows windows1 = new SaleWindows("窗口1", ticket);
        SaleWindows windows2 = new SaleWindows("窗口2", ticket);
        SaleWindows windows3 = new SaleWindows("窗口3", ticket);

        windows1.start();
        windows2.start();
        windows3.start();
    }
}

7、 生產者消費者
7.1 synchronized方式

public class FruitPlateDemo {

    private final static String LOCK = "lock";

    private int count = 0;

    private static final int FULL = 10;

    public static void main(String[] args) {

        FruitPlateDemo fruitDemo1 = new FruitPlateDemo();

        for (int i = 1; i <= 5; i++) {
            new Thread(fruitDemo1.new Producer(), "生產者-" + i).start();
            new Thread(fruitDemo1.new Consumer(), "消費者-" + i).start();
        }
    }

    class Producer implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                synchronized (LOCK) {
                    while (count == FULL) {
                        try {
                            LOCK.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    System.out.println("生產者 " + Thread.currentThread().getName() + " 總共有 " + ++count + " 個資源");
                    LOCK.notifyAll();
                }
            }
        }
    }

    class Consumer implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                synchronized (LOCK) {
                    while (count == 0) {
                        try {
                            LOCK.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("消費者 " + Thread.currentThread().getName() + " 總共有 " + --count + " 個資源");
                    LOCK.notifyAll();
                }
            }
        }
    }
}

7.2 ReentrantLock方式 (可以保證順序)

public class Demo1 {

    private int count = 0;

    private final static int FULL = 10;

    private Lock lock;

    private Condition notEmptyCondition;

    private Condition notFullCondition;

    {
        lock = new ReentrantLock();
        notEmptyCondition = lock.newCondition();
        notFullCondition = lock.newCondition();

    }

    class Producer implements Runnable {

        @Override
        public void run() {

            for (int i = 0; i < 10; i++) {
                lock.lock();
                try {
                    while(count == FULL) {
                        try {
                            notFullCondition.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("生產者 " + Thread.currentThread().getName() + " 總共有 " + ++count + " 個資源");
                    notEmptyCondition.signal();
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    class Consumer implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                lock.lock();
                try {
                    while(count == 0) {
                        try {
                            notEmptyCondition.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("消費者 " + Thread.currentThread().getName() + " 總共有 " + --count + " 個資源");
                    notFullCondition.signal();
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    public static void main(String[] args) {
        Demo1 demo1 = new Demo1();
        for (int i = 1; i <= 5; i++) {
            new Thread(demo1.new Producer(), "生產者-" + i).start();
            new Thread(demo1.new Consumer(), "消費者-" + i).start();
        }
    }
}

7.3 BlockingQueue方式

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class Demo2 {

    private int count = 0;

    private BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);

    public static void main(String[] args) {

        Demo2 demo2 = new Demo2();
        for (int i = 1; i <= 5; i++) {
            new Thread(demo2.new Producer(), "生產者-" + i).start();
            new Thread(demo2.new Consumer(), "消費者-" + i).start();
        }
    }

    class Producer implements Runnable {

        @Override
        public void run() {

            for (int i = 0; i < 10; i++) {
                try {
                    queue.put(1);
                    System.out.println("生產者 " + Thread.currentThread().getName() + " 總共有 " + ++count + " 個資源");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    class Consumer implements Runnable {

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                try {
                    queue.take();
                    System.out.println("消費者 " + Thread.currentThread().getName() + " 總共有 " + --count + " 個資源");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

8、交替打印兩個數組

package com.example.javatest.theardTest.MultiThreadAlgorithm;

public class TwoArr {

    int[] arr1 = new int[]{1, 3, 5, 7, 9};
    int[] arr2 = new int[]{2, 4, 6, 8, 10};

    boolean flag;

    public synchronized void print1(){
        for(int i= 0; i < arr1.length; i++){
            while (flag){
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            flag = !flag;
            System.out.println(arr1[i]);
            notifyAll();
        }
    }

    public synchronized void print2(){
        for(int i= 0; i < arr2.length; i++){
            while (!flag){
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            flag = !flag;
            System.out.println(arr2[i]);
            notifyAll();
        }
    }

    public static void main(String[] args) {

        TwoArr twoArr = new TwoArr();

        new Thread(new Runnable() {
            @Override
            public void run() {
                twoArr.print1();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                twoArr.print2();
            }
        }).start();
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章