`

多个线程到达后才能执行某个任务,并且只能执行一次

阅读更多
有一种场景:多个线程到达(比如合并多个线程返回的结果)后才能执行某个任务,并且只能执行一次。

有几种方式:
1、Thread的join,不再讲解,因为使用不方便,也是不建议使用的方式。
2、AtomicInteger ,其increaseAndGet 是非常方便实现这个需求的。
3、CountDownLatch ,这个组件也可以,并且在特定场景下,这个是最好的实现,比如有时间等待限制的。

下面看这个2 和 3的case。

import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 
 * @author xinchun.wang
 * @email: 532002108@qq.com
 * @createTime 2015-4-2 下午11:25:26
 */
public class AtomicExecute {
	private static final int all = 3;

	public static void main(String[] args) throws Exception {
		Vector<Integer> vector = new Vector<Integer>();
		AtomicInteger mask = new AtomicInteger(0);
		TestThread t1 = new TestThread(mask, vector, 1, 10);
		TestThread t2 = new TestThread(mask, vector, 11, 20);
		TestThread t3 = new TestThread(mask, vector, 21, 30);
		t1.start();
		t2.start();
		t3.start();

		Vector<Integer> vectorMain = new Vector<Integer>();
		for (int i = 1; i <= 30; i++) {
			vectorMain.add(i * i * i);
		}
		System.out.println("vectorMain: " + addVector(vectorMain));

	}

	private static long addVector(Vector<Integer> vector) {
		long result = 0;
		for (Integer item : vector) {
			result = result + item;
		}
		return result;
	}

	public static class TestThread extends Thread {
		private final AtomicInteger mask;
		private final Vector<Integer> vector;
		private int begin;
		private int end;

		public TestThread(AtomicInteger mask, Vector<Integer> vector,
				int begin, int end) {
			this.mask = mask;
			this.vector = vector;
			this.begin = begin;
			this.end = end;
		}

		@Override
		public void run() {
			for (int i = begin; i <= end; i++) {
				vector.add(i * i * i);
			}
			// do some things
			if (mask.incrementAndGet() == all) {
				System.out.println("vector: " + addVector(vector));
			}
		}
	}

}


/**
 * 
 * @author xinchun.wang
 * @email: 532002108@qq.com
 * @createTime 2015-4-2 下午11:25:26
 */
public class CountDown {
	private static final int all = 3;

	public static void main(String[] args) throws Exception {
		Vector<Integer> vector = new Vector<Integer>();
		CountDownLatch mask = new CountDownLatch(all);
		TestThread t1 = new TestThread(mask, 1, 10, vector);
		TestThread t2 = new TestThread(mask, 11, 20, vector);
		TestThread t3 = new TestThread(mask, 21, 30, vector);
		TestThread2 t4 = new TestThread2(mask, vector);
		t4.start();
		t1.start();
		t2.start();
		t3.start();

		Vector<Integer> vectorMain = new Vector<Integer>();
		for (int i = 1; i <= 30; i++) {
			vectorMain.add(i * i * i);
		}
		System.out.println("vectorMain: " + addVector(vectorMain));
	}

	private static long addVector(Vector<Integer> vector) {
		long result = 0;
		for (Integer item : vector) {
			result = result + item;
		}
		return result;
	}

	/**
	 * 输出结果的线程
	 */
	public static class TestThread2 extends Thread {
		private final CountDownLatch mask;
		private final Vector<Integer> vector;

		public TestThread2(CountDownLatch mask, Vector<Integer> vector) {
			this.mask = mask;
			this.vector = vector;
		}

		@Override
		public void run() {
			try {
				mask.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("vector: " + addVector(vector));
		}
	}

	/**
	 * 实际添加数据的线程
	 */
	public static class TestThread extends Thread {
		private final CountDownLatch mask;
		private int begin;
		private int end;
		private Vector<Integer> vector;

		public TestThread(CountDownLatch mask, int begin, int end,
				Vector<Integer> vector) {
			this.mask = mask;
			this.begin = begin;
			this.end = end;
			this.vector = vector;
		}

		@Override
		public void run() {
			for (int i = begin; i <= end; i++) {
				vector.add(i * i * i);
			}
			mask.countDown();
		}
	}
}
0
0
分享到:
评论

相关推荐

    linux下多定时器+线程池的实现(经典)

    //就把该回调函数添加到线程池的任务中,让线程池里面的线程去执行,然后将自定义定时器的超时时间置为最初值0; // // iv)用户通过del_a_timer来删除某个定时器,通 过destroy_mul_timer来删除整个多定时器。

    Java并发编程(学习笔记).xmind

    当多个线程访问某个类时,这个类始终能表现出正确的行为,那么就称这个类是线程安全的 无状态对象一定是线程安全的,大多数Servlet都是无状态的 原子性 一组不可分割的操作 竞态条件 基于一...

    自动化控制、事件触发机制研究

    程序此时启动一个线程来处理这个任务,用户界面上显示一个进度条指示用户任务执行的状态。这个功能就可以使用事件来进行处理。可以将处理任务的类作为消息的发送者,任务开始时,发出“TaskStart”事件,任务进行中...

    超级有影响力霸气的Java面试题大全文档

    最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概...

    java 面试题 总结

    最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概...

    another-challenge:另一个挑战

    找到一个指标来反映电梯的效率运行模拟以测试效率尝试不同的任务到达分布让每个任务在一定时间后到期(人们变得不耐烦并决定走路)第二次迭代第二,我要让电梯在每一步都承担多项任务。 假设: 每部电梯最多可承担 ...

    resin-jvm 调优

    增量收集器把堆栈分为多个域,每次仅从一个域收集垃圾。这会造成较小的应用程序中断。 2.5.分代收集器 这种收集器把堆栈分为两个或多个域,用以存放不同寿命的对象。jvm生成的新对象一般放在其中的某个域中。过一段...

    cmd操作命令和linux命令大全收集

    3. Nslookup-------IP地址侦测器 ,是一个 监测网络中 DNS 服务器是否能正确实现域名解析的命令行工具。它在 Windows NT/2000/XP 中均可使用,但在 Windows 98 中却没有集成这一个工具。 4. explorer-------打开...

    Windows 系统错误代码简单分析

     0149 试图连接或替换某个驱动器目录,该驱动器上的某个目录是上一次替换的目标目录。  0150 CONFIG.SYS 文件未指定系统跟踪信息,或禁止跟踪。  0151 DosMuxSemWait 的指定信号事件的数目不正确。  0152 ...

    C++网络爬虫项目

    管理器、统一资源定位符队列、域名解析线程等在内的多个底层设施,提供诸 如初始化、执行多路输入输出循环、启动抓取任务等外部接口。 2.3.5. 主线程(main) 主函数,处理命令行参数,初始化应用程序对象,进入多路I/...

Global site tag (gtag.js) - Google Analytics