java中的线程协调与线程间的数据交换

Java中提供多种方式协调线程的工作。

CountDownLatch:当多个也就是具体的数量等于CountDownLatch初始化参数的时候。线程达到了预期状态或者完成了预期工作时触发事件,其他线程可以等待这个事件来触发自己的后续工作。等待的线程是多个。达到了预期状态的线程会调用CountDownLatch的countDown方法。等待的线程会调用CountDownLatch的await方法。

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class CountDownLatchDemo {

	static ThreadPoolExecutor tp = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(5) );

	public static void main(String[] args) throws InterruptedException {
		int count = 10;
		final CountDownLatch latch = new CountDownLatch(count);
		int[] datas = new int[10240];
		int step = datas.length / count;
		for (int i=0; i<count; i++) {
			int start = i * step;
			int end = (i+1) * step;
			if (i == count -1)
				end = datas.length;

			tp.execute(new MyRunable(latch, datas, start, end));
		}

		latch.await();
	}
}
import java.util.concurrent.CountDownLatch;

public class MyRunable implements Runnable {
	CountDownLatch latch;
	int[] datas;
	 int start;
	 int end;

	public CountDownLatch getLatch() {
		return latch;
	}

	public void setLatch(CountDownLatch latch) {
		this.latch = latch;
	}

	public int[] getDatas() {
		return datas;
	}

	public void setDatas(int[] datas) {
		this.datas = datas;
	}

	public int getStart() {
		return start;
	}

	public void setStart(int start) {
		this.start = start;
	}

	public int getEnd() {
		return end;
	}

	public void setEnd(int end) {
		this.end = end;
	}

	public MyRunable(CountDownLatch latch, int[] datas, int start, int end) {
		this.latch = latch;
		this.datas = datas;
		this.start = start;
		this.end = end;
	}

	@Override
	public void run() {
		latch.countDown();
	}

}

CyclicBarrier是指循环屏障。它可以协同多个线程,让多个线程在这个屏障前等待。直到所有的线程都达到了这个屏障,再一起继续执行后面的工作。

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class CyclicBarrierDemo {

	static ThreadPoolExecutor tp = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(5) );

	public static void main(String[] args) throws InterruptedException {
		int count = 10;
		final CyclicBarrier latch = new CyclicBarrier(count);
		int[] datas = new int[10240];
		int step = datas.length / count;
		for (int i=0; i<count; i++) {
			int start = i * step;
			int end = (i+1) * step;
			if (i == count -1)
				end = datas.length;

			tp.execute(new MyRunable1(latch, datas, start, end));
		}

		try {
			latch.await();
		} catch (BrokenBarrierException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

CyclicBarrier与CountDownLatch都用于线程之间的协调。两者之间的差别在于,CountDownLatch是在多个线程都进行了latch.countDown方法后,才会触发事件,唤醒await在latch上的线程。而执行countDown的线程,行完countDown后会继续自己的线程工作。CyclicBarrier用于同步所有调用await方法的线程,并且等待所有线程都到await方法时,这些线程才继续各自的工作。

Exchanger

不同线程之间的数据交换用Exchanger。当一个线程的方法执行调用exchanger.exchange的时候,会等待其他线程也执行到调用这个方法。然后交换彼此之间的数据

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Exchanger;

public class ExchangerDemo {

	public static void main(String[] args) {
		final Exchanger<List<Integer>> exchanger = new Exchanger<List<Integer>>();
		new Thread(){
			public void run(){
				List<Integer> list = new ArrayList<Integer>(2);
				list.add(1);
				list.add(2);

				try {
					list = exchanger.exchange(list);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("thread1:" + list);
			}
		}.start();

		new Thread(){
			public void run(){
				List<Integer> list = new ArrayList<Integer>(3);
				list.add(3);
				list.add(4);
				list.add(5);
				try {
					list = exchanger.exchange(list);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("thread2:" + list);
			}
		}.start();

	}
}

时间: 2024-10-20 11:35:49

java中的线程协调与线程间的数据交换的相关文章

Java 中几种常用的线程池

Java 中几种常用的线程池 转载 : https://www.cnblogs.com/sachen/p/7401959.html 原创 2016年04月14日 23:29:01 标签: java / 线程池 / Executor 878 概述: 在java内置API中操作线程所用到的类为Thread.创建线程一般有两种方式, 继承Thread方式 实现Runnable方式,并以runnable作为target创建Thread 在Android中的耗时任务一般都需要另开线程来执行,常常需要用线程

Java--Exchanger用于进行线程间的数据交换

package com; import java.util.concurrent.Exchanger; /** * Created by yangyu on 16/11/28. */ /** * Exchanger用于进行线程间的数据交换: * 它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据: * 两个线程通过exchange方法交换数据,如果一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange方法 * 当两个线程都达到同步点时,这两个线程就可以交换数据,

Java核心知识点学习----多线程 倒计时记数器CountDownLatch和数据交换的Exchanger

本文将要介绍的内容都是Java5中的新特性,一个是倒计时记数器---CountDownLatch,另一个是用于线程间数据交换的Exchanger. 一.CountDownLatch 1.什么是CountDownLatch? 倒计时计数器,调用CountDownLatch对象的CountDown()方法就将计数器减一,当计数到达0时,则所有等待者或者全部等待者开始执行. 2.如何用? new CountDownLatch(1); 直接new,其构造函数必须传一个int类型的参数,参数的意思是: c

[笔记][Java7并发编程实战手冊]3.8 并发任务间的数据交换Exchanger

[笔记][Java7并发编程实战手冊]系列文件夹 简单介绍 Exchanger 是一个同步辅助类.用于两个并发线程之间在一个同步点进行数据交换. 同意两个线程在某一个点进行数据交换. 本章exchanger 使用心得总结 两个线程必须使用同一个Exchanger对象,且仅仅能是两个线程间的数据交换 exchanger.exchange(v)的时候,当前线程会被堵塞,直到还有一个线程运行该方法,同一时候完成数据的交换 相似这样的数据交换的,生产者线程一定要先生产数据.再交换数据,消费者线程一定要先

java中的并发:进程和线程

1.简介 1)进程:同一个系统中执行的一个子程序,包含三部分:虚拟CPU,代码,数据. 2)线程:同一个进程中执行的子程序流. 3)进程让操作系统的并发性成为可能,而线程让进程的内部并发成为可能.一个进程虽然包括多个线程,但是这些线程是共同享有进程占有的资源和地址空间的.进程是操作系统进行资源分配的基本单位,而线程是操作系统进行调度的基本单位. 2.创建一个进程 2.1首先了解三个类    1)Process(抽象类)       进程类,提供了执行从进程输入.执行输出到进程.等待进程完成.检查

在java中怎样实现多线程?线程的4种状态

一.在java中怎样实现多线程? extends Thread implement Runnable 方法一:继承 Thread 类,覆盖方法 run(),我们在创建的 Thread 类的子类中重写 run() ,加入线程所要执行的代码即可. 下面是一个例子: public class MyThread extends Thread { int count= 1, number; public MyThread(int num) { number = num; System.out.printl

Java中常用的四种线程池

在Java中使用线程池,可以用ThreadPoolExecutor的构造函数直接创建出线程池实例,如何使用参见之前的文章Java线程池构造参数详解.不过,在Executors类中,为我们提供了常用线程池的创建方法.接下来我们就来了解常用的四种: newFixedThreadPool 首先,看一下这种线程池的创建方法: public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExec

简谈Java中常用的四种线程池

newFixedThreadPool 首先,看一下这种线程池的创建方法: public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } 从构造方法可以看出,它创建了一个固定大小的线程池,每次提交一

ajax传JSON时设置的contenttype导致JAVA中request.getParameter(&quot;&quot;)怎么也接收不到数据

ajax传JSON时设置的contenttype默认值是application/x-www-form-urlencoded, 当ajax传JSON时设置的contenttype 如果是application/json或者text/json时,JAVA中request.getParameter("")是接收不到数据的. 因为在java后台会认为你传递的是一个纯文本流,而非键值对,是不能存入requestMap的. 可以把流读取出来转成json转成lsit或对象等,在Spring中使用@R