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 方法执行结束后;

相关文章
相关标签/搜索