java多線程通訊

最近在研究java多線程,這篇文章主要是介紹一些線程之間的通訊:java

1:join 的方式,一個線程等待另外一個線程執行完畢後在執行,能夠控制線程執行的順序;多線程

場景:B線程要在A線程完成後纔開始任務:ide

不作任何控制的狀況下的線程代碼以下:spa

@Test
    public void threadTest4() throws InterruptedException, ExecutionException {
//        線程A
        final Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                printNum("線程A");
            }
        });
//        線程B
        Thread threadB= new Thread(new Runnable() {
            @Override
            public void run() {
//                try {
//                    threadA.join();
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
                printNum("線程B");
            }
        });

        threadA.start();
        threadB.start();
        Thread.sleep(1000);
    }
private void printNum(String threadName){
        int i=0;
        while (i++<3){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(threadName+"打印"+i);
        }
    }

這樣打印出來的效果以下:線程

線程B打印1
線程A打印1
線程B打印2
線程A打印2
線程B打印3
線程A打印3

這樣不能保證 B 線程在A 線程執行完以後再執行;能夠經過 join 方法來實現咱們的需求: 當在 B 線程調用 A線程的join 方法 則會 B 線程等待A線程執行完了以後再執行B 線程;將上面注掉的代碼解開就好了;code

這樣打印出來的效果是:對象

線程A打印1
線程A打印2
線程A打印3
線程B打印1
線程B打印2
線程B打印3

這樣就能保證 B 線程在 A線程執行結束後再執行;blog

2:多個線程按照必定的順序交叉執行:get

場景:A 線程執行打印完 1 2 後 B 線程再執行打印 1 2 3 同步

這樣的場景須要使用 鎖的等待和喚醒的機制來實現,代碼實現以下:  須要用到兩個方法 wait  和 notify 方法  這兩個方法都是 Object對象的方法;

@Test
    public void threadTest5() throws InterruptedException, ExecutionException {
        final Object o=new Object();
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (o){
                    System.out.println("線程A 打印 1");
                    try {
                        o.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("線程A 打印 2");
                    System.out.println("線程A 打印 3");
                }

            }
        });

        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (o){
                    System.out.println("線程B 打印 1");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("線程B 打印 2");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("線程B 打印 3");
                    o.notify();
                }

            }
        });
        threadA.start();
        threadB.start();
        Thread.sleep(1000);
    }

下面分析這段代碼的執行順序:

1:建立對象鎖 

final Object o=new Object();

2:A 首先得到對象鎖的控制權;

3:A 調用  wait 方法 讓出對象鎖的控制權:

o.wait();

4:B 線程得到對象鎖的控制權:

B線程的業務代碼處理完以後 調用 notify 方法,喚醒 正在 wait  的線程 而後結束B線程的同步代碼塊,

5:A 線程獲取到了對象鎖的控制權後執行本身的業務邏輯;

這樣就知足咱們須要的場景;

3: 四個線程 A B C D,其中 D 要等到 A B C 全執行完畢後才執行,並且 A B C 是同步運行的

經過 調用對象鎖的 notify 和 wait 方法能夠知足線程的執行順序 可是線程是一次執行的,不能同時進行;

須要同步進行有須要進行控制線程的執行順序則可使用 線程計數器來實現  

代碼以下:

@Test
    public void threadTest1() throws InterruptedException {
        int worker = 3;
        System.out.println("計數器的值爲:" + worker);
        final CountDownLatch countDownLatch = new CountDownLatch(worker);
        Thread threadD = new Thread(new Runnable() {
            @Override
            public void run() {

                System.out.println("D 線程等待其餘線程!");
                try {
                    countDownLatch.await();
                    System.out.println("其餘線程運行結束,D線程開始");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        threadD.start();

        for (int i = 0; i < 3; i++) {

            final int finalI = i;
            Thread threadA = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + finalI + "is working");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + finalI + "is finish");
                    countDownLatch.countDown();
                }
            });
            threadA.start();
        }

        Thread.sleep(1000);

    }

  上面代碼的執行順序以下:

1:建立線程計數器:計數器的計數個數爲3;

2:當D線程開始執行的時候調用計數器的 await 方法,而後等待;

3:執行 ABC 線程的業務邏輯的處理,在線程的業務邏輯處理以後分別調用 計數器的 數字減1.

4:當計數器的數值爲0 時D線程得到執行權,開始執行;

 

4:多線程獲取線程處理的返回值:

代碼以下:

@Test
    public void threadTest3() throws InterruptedException, ExecutionException {
        Callable<Integer> callable = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                System.out.println("開始任務!!");
                Thread.sleep(100);
                int result=0;
                for (int i = 0; i <100 ; i++) {
                    result +=i;
                }
                return result;
            }
        };
        FutureTask<Integer> futureTask = new FutureTask<Integer>(callable);
        new Thread(futureTask).start();
        System.out.println("任務獲取前");
        System.out.println("任務獲取到的結果是:"+futureTask.get());
        System.out.println("任務獲取後");
        Thread.sleep(1000);

    }

經過Callable  和 FutureTask 兩類能夠實現這個功能, 注意 FutureTask  的 get()方法是同步,必須在callable中的call 方法執行結束後;

相關文章
相關標籤/搜索