Java多线程之线程协作

无意中在一篇文章中看到一个面试题,题目内容为:现有一个统计任务,需要3个线程完成,在这三个线程完成后由一个线程完成最后的统计报告工作,写出大概代码。
其实多线程问题都可以从两个角度考虑实现,一种是java5之前的同步关键字去实现,另一种是java5之后提供的多线程新特性角度去考虑。
对于传统的同步关键字思路:四个线程都共享一个信号量,当信号量标志子线程任务都完成时,唤醒最后的统计线程;对于java5并发包的思路:java5对于该类线程协作问题提供了CountDownLatch、CyclicBarrier、Semaphore等工具类,拿过来就可以用,这里可以用CountDownLatch工具类,该工具类作用是某个任务需要等待其他几个任务完成后才能开始执行。下面给出源码:
同步关键字:

package countdownlatch.Test2;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by dingxiangyong on 2016/3/25.
 */
public class Test {


    public static void main(String[] args) {

        Statistic statistic = new Statistic();


        /**
         * 信号量
         */
        Single single = new Single(3);

        StatisticSubTask task1 = new StatisticSubTask(statistic, single);
        StatisticSubTask task2 = new StatisticSubTask(statistic, single);
        StatisticSubTask task3 = new StatisticSubTask(statistic, single);

        StatisticAllTask taskAll = new StatisticAllTask(statistic, single);

        ExecutorService service = Executors.newFixedThreadPool(4);
        service.execute(task1);
        service.execute(task2);
        service.execute(task3);
        service.execute(taskAll);

        service.shutdown();
    }
}

class StatisticSubTask implements Runnable{

    private Statistic statistic;

    private Single single;

    public StatisticSubTask(Statistic statistic, Single single) {
        this.statistic = statistic;
        this.single = single;
    }

    @Override
    public void run() {

        try {
            Thread.sleep(1000); //模拟统计耗时操作
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (statistic) {
            statistic.result.add(new Object());
        }
        //减少信号量
        synchronized(single) {

            single.countDown();
            if (single.isEmpty()) {
                single.notify();
            }
        }
    }
}

class StatisticAllTask implements Runnable{
    private Statistic statistic;

    private Single single;

    public StatisticAllTask(Statistic statistic, Single single) {
        this.statistic = statistic;
        this.single = single;
    }

    @Override
    public void run() {
        synchronized(single) {
            //看信号量,决定是否可以继续处理
            while(!single.isEmpty()) {
                try {
                    single.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("result : " + statistic.result.size());
    }
}

/**
 * 统计结果
 */
class Statistic {
    public List<Object> result = new ArrayList<Object>();
}

class Single {
    private Integer count = 0;

    public Single(Integer count) {
        this.count = count;
    }

    public void countDown() {
        this.count --;
    }

    public boolean isEmpty() {
        return this.count == 0;
    }
}

CountDownLatch实现:

package countdownlatch;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by dingxiangyong on 2016/3/25.
 */
public class Test {

    public static void main(String[] args) {

        /**
         * 统计结果
         */
        Statistic statictis = new Statistic();

        /**
         * 协同其他线程的锁
         */
        CountDownLatch latch = new CountDownLatch(3);

        StatisticSubTask task1 = new StatisticSubTask(latch, statictis);
        StatisticSubTask task2 = new StatisticSubTask(latch, statictis);
        StatisticSubTask task3 = new StatisticSubTask(latch, statictis);

        StatisticAllTask taskAll = new StatisticAllTask(latch, statictis);

        ExecutorService service = Executors.newFixedThreadPool(4);
        service.execute(task1);
        service.execute(task2);
        service.execute(task3);
        service.execute(taskAll);

        service.shutdown();
    }
}

class StatisticSubTask implements Runnable {

    /**
     * 协同其他线程的锁
     */
    private CountDownLatch latch;

    private Statistic statictis;

    public StatisticSubTask(CountDownLatch latch, Statistic statictis) {
        this.latch = latch;
        this.statictis = statictis;
    }

    @Override
    public void run() {

        try {
            Thread.sleep(1000); //模拟统计耗时操作
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (statictis) {
            statictis.result.add(new Object());
        }
        latch.countDown(); //通知其他线程本线程任务已完成
    }

    ;
}

class StatisticAllTask implements Runnable {

    /**
     * 协同其他线程的锁
     */
    private CountDownLatch latch;

    private Statistic statictis;

    public StatisticAllTask(CountDownLatch latch, Statistic statictis) {
        this.latch = latch;
        this.statictis = statictis;
    }

    @Override
    public void run() {
        try {
            latch.await();//等待其他统计线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("result : " + statictis.result.size());
    }

    ;
}

/**
 * 统计结果
 */
class Statistic {
    public List<Object> result = new ArrayList<Object>();
}

对比代码,使用新特性CountDownLatch之后代码变得优雅许多。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值