java5 of thread concurrency library

In java.util.concurrent package and subpackages

1. atomicity operation class

java provides many atomic operations class for us to use, thread-safe programming support to lift lock on a single variable.

1.1 AtomicInteger class

Can be atomically updated intvalue when multiple threads share a int data type, we can make the variable AtomicInteger type.

1.1.1 addAndGet(int delta)

Atomically add the given value to the current value of

1.1.2 getAndIncrement

Atomically add a current value.

1.1.3 decrementAndGet

Atomically current value by one.

Other specific API can refer to the JDK API documentation

1.2 AtomicIntegerArray类

Array for integer operations

Reference JDK API documentation

1.3 AtomicIntegerFieldUpdater类

Integer operations for the object

JDK API Reference

2. Thread Pool

2.1 Tools Executors

Executors inside the package a lot of static methods to create a thread for us to create a thread

2.1.1 fixed number of thread pool --newFixedThreadPool

ExecutorService pool = Executors.newFixedThreadPool(3);
for(int i = 0 ; i < 10 ; i++){
	final int task = i;
	pool.execute(new Runnable() {
		@Override
	    public void run() {
			System.out.println(Thread.currentThread().getName() + "  " + task);
		}
	});
}

2.1.2 cached thread pool --newCachedThreadPool

ExecutorService pool = Executors.newCachedThreadPool();

2.1.3 only one thread of the thread pool --newSingleThreadExecutor

ExecutorService pool = Executors.newSingleThreadExecutor();

Note: The way compared to the traditional way to create threads, one advantage is that if the thread pool is dead, it will create a thread pool thread 

2.2 thread pool is closed

1. shutdown()

2. shutdownNow()

Two methods have closing function of the thread pool, the first way, as well as the executing thread pool, then wait for the finished, closed, the second way, regardless of whether there is a pool of threads being executed, They are closed.

2.3 thread pool starts a timer

2.3.1 newScheduledThreadPool

1. schedule method, how much time after execution

10 seconds after execution

ScheduledExecutorService sPool = Executors.newScheduledThreadPool(3);
sPool.schedule(new Runnable() {
		@Override
		public void run() {
			System.out.println("嘭");
		}
}, 10, TimeUnit.SECONDS);

2. scheduleAtFixedRate method, performed at a fixed frequency 

Started 10 seconds, performed every 2 seconds later

ScheduledExecutorService sPool = Executors.newScheduledThreadPool(3);
sPool.scheduleAtFixedRate(new Runnable() {
	@Override
	public void run() {
		System.out.println("嘭");
	}
}, 10, 2,TimeUnit.SECONDS);

2.3.2 newSingleThreadScheduledExecutor

Create a single timed thread pool, use ibid.

3. With return results thread

3.1 Callable与Future

Callable and Future Role of the program is to start a thread, the thread after the end of the run, the results can be returned after the thread is finished.

Type 1. Future results achieved must be consistent with the type Callable return, which is achieved by generics.

2. Callable to be used ExecutorService the submit method to submit, Future returned object can be canceled task.

E.g:

public static void main(String[] args) throws Exception, ExecutionException {
	// 创建一个线程池
	ExecutorService service = Executors.newSingleThreadExecutor();
	// 提交任务返回线程执行的结果
	Future<Map<String,String>> future = service.submit(new Callable<Map<String,String>>() {
		@Override
		public Map<String,String> call() throws Exception {
			Map<String,String> map = new HashMap<String,String>();
			map.put("msg", "执行成功");
			return map;
		}
	});
	// 得到结果
	Map<String, String> map = future.get();
	System.out.println(map);
}

Note: Callable support generics, generic type is the return type of the method call, the type is Future generic type.

For example: As with String return value

public static void main(String[] args) throws Exception, ExecutionException {
	// 创建一个线程池
	ExecutorService service = Executors.newSingleThreadExecutor();
	// 提交任务返回线程执行的结果
	Future<String> future = service.submit(new Callable<String>() {
		@Override
		public String call() throws Exception {			
			return "ok";
		}
	});
	
	String rtnResult = future.get();
	System.out.println(rtnResult);
}

3.2 CompletionService

CompletionService for submitting a set Callable task, which take a Callable method returns the corresponding task has been completed Future object.

CompletionService is an interface, we create their objects using a subclass ExecutorCompletionService, constructor accepts a thread object.

API

1. submit: to perform a task, the parameter is a task object, such as Callable

2. take: get the task completed execution of the Future object

For example: Create a group thread task to task execution, and get return values

public static void main(String[] args) throws Exception, ExecutionException {
	// 创建一个固定大小的线程池
	ExecutorService pool = Executors.newFixedThreadPool(10);
	// 创建一个任务组
	CompletionService<Integer> cService = new ExecutorCompletionService<Integer>(pool);
	// 创建10个任务,并交给任务组执行
	for(int i = 0 ; i < 10 ; i++){
		final Integer seq = i;
		cService.submit(new Callable<Integer>() {
			@Override
			public Integer call() throws Exception {
				Thread.sleep(new Random().nextInt(10000));
				// 返回线程编号
				return seq;
			}
		});
	}
		
	// 获取线程执行结果
	for(int i = 0 ; i < 10 ; i++){
		// 得到已经执行完毕的任务的返回结果的Future对象
		Future<Integer> take = cService.take();
		// 获取返回结果
		Integer result = take.get();
		System.out.println(result);
	}
}

3. Thread lock

3.1 Lock

        lock thread than the traditional model of synchronized way more object-oriented, and life in similar lock, the lock itself should be an object. Code snippet to execute two threads synchronize mutually exclusive effect, they must use the same Lock object. Lock is to be operated on behalf of internal resource class method, instead of threaded code.

        Lock is an interface we want to use, generally create an instance of its subclasses.

For example: Lock lock = new ReentrantLock ();

private Lock lock = new ReentrantLock();
public void lockTest01() {
	lock.lock();  // 上锁
	try {
		for(int i = 0 ; i < 100 ; i++){
			System.out.println("张三");
		}
	} finally {
		lock.unlock(); // 释放锁
	}
		
}

Note: There is a reason finally, placing the code is abnormal, leading to the lock can not be released. 

3.1.1 Read-Write Lock --ReadWriteLock

        Lock is divided into read-write locks, multiple read locks are not mutually exclusive, exclusive write locks and read locks, write locks and exclusive write locks, which is controlled by the JVM themselves, as long as you can Shanghao corresponding lock.

        If your code is read-only data, at the same time a lot of people can read, but not write at the same time, it is a read lock;

        If you modify the code data, only one person in writing and can not be read at the same time, then the write lock. In short, read lock on the read, write lock on the time of writing.

ReadWriteLock is an interface, we use it to create a subclass ReentrantReadWriteLock lock object and then call readLock for reading respectively, writeLock used to write

E.g:

package com.bjc.thread.demo4;

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockTest {
	public static void main(String[] args) {
		final Queue3 q3 = new Queue3();
		for(int i=0;i<3;i++){
			new Thread(){
				public void run(){
					while(true){
						q3.get();						
					}
				}
				
			}.start();

			new Thread(){
				public void run(){
					while(true){
						q3.put(new Random().nextInt(10000));
					}
				}			
				
			}.start();
		}
		
	}
}

class Queue3{
	private Object data = null;//共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。
	ReadWriteLock rwl = new ReentrantReadWriteLock();
	public void get(){
		rwl.readLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + " be ready to read data!");
			Thread.sleep((long)(Math.random()*1000));
			System.out.println(Thread.currentThread().getName() + "have read data :" + data);			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwl.readLock().unlock();
		}
	}
	
	public void put(Object data){

		rwl.writeLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + " be ready to write data!");					
			Thread.sleep((long)(Math.random()*1000));
			this.data = data;		
			System.out.println(Thread.currentThread().getName() + " have write data: " + data);					
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwl.writeLock().unlock();
		}
		
	
	}
}

A custom cache class

package com.bjc.thread.demo4;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class CacheDemo {

	private Map<String,Object> cache = new HashMap<String,Object>();
	ReadWriteLock rwl = new ReentrantReadWriteLock();
	
	/**
	 * @param key
	 * @return
	 * 当有多个线程同时读的时候,当线程1发现value为null,那么线程1就会查询数据库
	 * 写数据,这时候,线程2也进来了,也要写数据,所以,我们这里设计一个写锁,当线程1
	 * 写数据的时候,其他线程等待线程1写锁释放之后,在开始并发读数据
	 */
	public Object getData(String key){
		rwl.readLock().lock();
		Object value = null;
		try {
			value = cache.get(key);
			if(null == value){
				rwl.readLock().unlock();  // 开始写的时候,释放读锁
				rwl.writeLock().lock();
				try {
					/*
					 * 这里在加一次判断,是因为当线程1和线程2线程3同时读到30行rwl.writeLock().lock();的时候
					 * 只有一个线程会拿到写锁,这时候,当该线程写完数据,释放掉写锁的时候,另外两个线程会接着拿着写锁,‘
					 * 去写数据,导致资源的无畏的浪费。所以这里再加一个判断。
					 * */
					if(null == value){
						value = "查询数据库!";
					}
				} finally{
					// 读到了数据释放写锁
					rwl.writeLock().unlock();
					// 再回复读锁
					rwl.readLock().lock();
				}
			}
		} finally {
			rwl.readLock().unlock();  // 前面已经释放了读锁了,这里再次释放
		}
		return value;
	}

}

 

3.2 execution condition Condition

        Lock can only be achieved mutually exclusive, but can not communicate, then we need to introduce an API to communicate.

        Condition of the traditional functions like thread technology and Object.wait Object.notify functions, while waiting Condition, allow spurious wakeup occurs, it is usually as a concession to the underlying platform semantics.

        For most applications, this brings the actual impact is very small, because the Condition should always be waited upon in a loop, and test status being declared wait. Free to remove possible to achieve a false wake up, it is recommended that the application is always assumed these false wake-up may occur, so always wait in a loop.

3.3.1 Important API

1. Obtain Condition objects

Condition condition = lock.newCondition()

2. Wait

condition .await();

3. Wake

condition .signal()

condition .signalAll()

3.3.2 Case

package com.bjc.thread.demo5;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyThread {
	private Boolean flag = true;
	private Lock lock = new ReentrantLock();
	Condition condition = lock.newCondition();
	
	public void sub(int i){
		try {
			lock.lock();
			while(flag){
				condition.await();
			}
			for(int j=1;j<=10;j++){
				System.out.println("sub  " + j + ",from " + i);
			}
			flag = true;
			condition.signal();
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			lock.unlock();
		}
	}
	
	public void main(int i) {
		try {
			lock.lock();
			while(!flag){
				condition.await();
			}
			for(int j=1;j<=100;j++){
				System.out.println("main  " + j + ",from " + i);
			}
			flag = false;
			condition.signal();
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			lock.unlock();
		}
	}
	
}

transfer

package com.bjc.thread.demo5;

public class Demo1 {

	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		new Thread(){
			@Override
			public void run() {
				for(int i=1;i<=50;i++){
					myThread.sub(i);
				}
			};
		}.start();
		for(int i=1;i<=50;i++){
			myThread.main(i);
		}
	}
}

3.3.3 Conditions blocking queue

        By the button above, we find, Condition of usage and traditional usage and the role of thread communication almost, in that case, why do we need to introduce a Condition? This is because the application conditions can be realized Condition blocking queue that is waiting for multiple notifications. 

        An internal lock can have multiple Condition, namely a number of road and wait for notification, you can see Applications can clog the queue Lock and Condition achieve. In conventional threading mechanism, the only way to wait on a monitor object and notice, in order to achieve multi-channel and wait for notification, must be nested using multiple monitors synchronization objects, create multiple Condition

See the example given JDK

class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition(); 
   final Condition notEmpty = lock.newCondition(); 

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length) 
         notFull.await();
       items[putptr] = x; 
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0) 
         notEmpty.await();
       Object x = items[takeptr]; 
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   } 
 }

Another more classic example of a three threads run alternately

E.g:

public class ThreeConditionCommunication {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		final Business business = new Business();
		new Thread(
				new Runnable() {
					
					@Override
					public void run() {
					
						for(int i=1;i<=50;i++){
							business.sub2(i);
						}
						
					}
				}
		).start();
		
		new Thread(
				new Runnable() {
					
					@Override
					public void run() {
					
						for(int i=1;i<=50;i++){
							business.sub3(i);
						}
						
					}
				}
		).start();		
		
		for(int i=1;i<=50;i++){
			business.main(i);
		}
		
	}

	static class Business {
			Lock lock = new ReentrantLock();
			Condition condition1 = lock.newCondition();
			Condition condition2 = lock.newCondition();
			Condition condition3 = lock.newCondition();
		  private int shouldSub = 1;
		  public  void sub2(int i){
			  lock.lock();
			  try{
				  while(shouldSub != 2){
					  try {
						condition2.await();
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				  }
					for(int j=1;j<=10;j++){
						System.out.println("sub2 thread sequence of " + j + ",loop of " + i);
					}
				  shouldSub = 3;
				  condition3.signal();
			  }finally{
				  lock.unlock();
			  }
		  }

		  public  void sub3(int i){
			  lock.lock();
			  try{
				  while(shouldSub != 3){
					  try {
						condition3.await();
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				  }
					for(int j=1;j<=20;j++){
						System.out.println("sub3 thread sequence of " + j + ",loop of " + i);
					}
				  shouldSub = 1;
				  condition1.signal();
			  }finally{
				  lock.unlock();
			  }
		  }		  
		  
		  public  void main(int i){
			  lock.lock();
			  try{
				 while(shouldSub != 1){
				  		try {
							condition1.await();
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
				  	}
					for(int j=1;j<=100;j++){
						System.out.println("main thread sequence of " + j + ",loop of " + i);
					}
					shouldSub = 2;
					condition2.signal();
		  }finally{
			  lock.unlock();
		  }
	  }
	
	}
}

4. Semaphere synchronization tool (semaphore)

4.1 Overview

         Semaphore also called light technology, is a facility for use in a multithreaded environment, the facility is responsible for coordinating the various threads, to ensure that they can correct and reasonable use of the facilities of public resources, but also the operating system for controlling cross-process synchronization the amount of repellent. Semaphore is a counting semaphore for managing a set of resources is based on a shared mode inside the AQS. It is equivalent to thread a prescribed amount so as to control the number of threads to allow activities.

        In simple terms, the number of threads Semaphere can maintain their current access, and provides a synchronization mechanism, using Semaphere can control the number of threads simultaneously access a resource, such as: to achieve a number of concurrent access to files allowed.

      Its essence is a shared lock.

4.2 Important API

4.2.1 Constructor

Semaphore (int permits): Creates a given number counting semaphores and sets the non-permission signal fair amount.

Semaphore (int permits, boolean fair): When the fair is equal to true, creating a given counting semaphores and license number to a fair amount of signal, i.e., when the fair = true when advanced to the first implementation.

Note: a single semaphore Semaphore mutex object can implement functions, and can be obtained by a thread lock, and then by another thread releases the lock, the deadlock can be used in some cases to recover

4.2.2 acquisition

void acquire (): Acquires a permit from this semaphore, the current thread will block. They accounted for the equivalent of a car parking space.

void acquire (int n): this semaphore acquisition of a given number of licenses, the thread has been blocked until all are available. For example, n = 2, the equivalent of a car accounted for two parking spaces

void acquireUninterruptibly (): this semaphore acquired the license before the license is available which is blocked

void acquireUninterruptibly (int permits): this semaphore to get permission given number, it has been blocked in the thread until all are available.

int availablePermits (): number of licenses currently available

int drainPermits (): Get and return all permits that are immediately available

protected Collection <Thread> getQueuedThreads (): Returns a collection, it contains threads may be waiting to acquire.

int getQueueLength (): Returns the estimated number of acquisition are waiting threads.

boolean hasQueuedThreads (): Query whether any threads are waiting to acquire

boolean isFair (): If this semaphore fair set to true, return true

4.2.3 release signal

void release (): release of a permit, returning it to the semaphore. Just as the car drove off to return a parking space

void release (int n): n release licenses.

E.g:

package com.bjc.thread.demo6;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreTest {
	public static void main(String[] args) {
		// 创建一个缓存线程池
		ExecutorService service = Executors.newCachedThreadPool();
		// 创建一个有3个信号量的信号灯
		final  Semaphore sp = new Semaphore(3);
		for(int i=0;i<10;i++){
			Runnable runnable = new Runnable(){
				public void run(){
					try {
						// 获取许可
						sp.acquire();
					} catch (InterruptedException e1) {
						e1.printStackTrace();
					}
					System.out.println("线程" + Thread.currentThread().getName() + 
							"进入,当前已有" + (3-sp.availablePermits()) + "个并发");
					try {
						Thread.sleep((long)(Math.random()*10000));
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println("线程" + Thread.currentThread().getName() + 
							"即将离开");		
					// 执行完毕,释放信号灯
					sp.release();
					//下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
					System.out.println("线程" + Thread.currentThread().getName() + 
							"已离开,当前已有" + (3-sp.availablePermits()) + "个并发");					
				}
			};
			// 执行线程
			service.execute(runnable);			
		}
	}

}

4.3 Case

4.3.1 Case 1-- unfair signals

The number of threads in order to create objects with Semphore class initialization semaphore, movable control

package com.bjc.thread.demo6;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.LinkedBlockingQueue;
public class TestDemo1 {
	private static final Semaphore semaphore=new Semaphore(3);
	private static final ThreadPoolExecutor threadPool=new ThreadPoolExecutor(5,10,60,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());
	
	private static class InformationThread extends Thread{
		private final String name;
		private final int age;
		public InformationThread(String name,int age) {
			this.name=name;
			this.age=age;
		}
		
		public void run() {
			try {
				semaphore.acquire();
				System.out.println(Thread.currentThread().getName()+":大家好,我是"+name+"我今年"+age+"岁");
				Thread.sleep(1000);
				System.out.println(name+"要准备释放许可证了");
				System.out.println("当前可使用的许可数为:"+semaphore.availablePermits());
				semaphore.release();
			} catch(InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) {
		String[] name= {"纪大","和二","张三","李四","王五","赵六","钱七"};
		for(int i=0;i<7;i++) {
			Thread t1=new InformationThread(name[i],(i + 1 * 23));
			threadPool.execute(t1);
		}
	}
 
}

4.3.2 Case 2-- fair lights

Just to the above-described private static final Semaphore semaphore = new Semaphore (3); into private static final Semaphore semaphore = new Semaphore (3, true); to.

Note: The so-called fair, is the first in first out

4.3.3 Singleton Pattern achieve

Just to private static final Semaphore semaphore = new Semaphore (3) into private static final Semaphore semaphore = new Semaphore (1) can, that is, the number of the semaphore constructor is 1 on the line

5. CyclicBarrier synchronization tool (fence)

5.1 Overview

        CyclicBarrier is a synchronization aid that allows a set of threads waiting for each other to reach a common barrier point (common barrier point). Relates to a set of program threads fixed size, these threads must wait for each other from time to time, this time CyclicBarrier useful. Since the barrier can be reused after the release waiting threads, so called barrier loop.

        CyclicBarrier supports an optional Runnable command, after the last set of threads in a thread of arrival (but before the release of all threads), the command only once per barrier point run. If the update sharing status before continuing to participate in all threads, this barrier action is useful.

5.2 Important API

5.3.1 Constructor

CyclicBarrier ( int  parties): Setting parties, count and barrierCommand property

CyclicBarrier (int parties, Runnable barrierAction): When the number of set number await the arrival of the first implementation Runnable object

5.3.2 Other API

await (): inform the barrier has been completed thread 

E.g:

package com.bjc.thread.demo6;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CyclicBarrierTest {

	public static void main(String[] args) {
		ExecutorService service = Executors.newCachedThreadPool();
		final  CyclicBarrier cb = new CyclicBarrier(3);
		for(int i=0;i<3;i++){
			Runnable runnable = new Runnable(){
					public void run(){
					try {
						Thread.sleep((long)(Math.random()*10000));	
						System.out.println("线程" + Thread.currentThread().getName() + 
								"即将到达集合地点1,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));						
						cb.await();
						
						Thread.sleep((long)(Math.random()*10000));	
						System.out.println("线程" + Thread.currentThread().getName() + 
								"即将到达集合地点2,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));
						cb.await();	
						Thread.sleep((long)(Math.random()*10000));	
						System.out.println("线程" + Thread.currentThread().getName() + 
								"即将到达集合地点3,当前已有" + (cb.getNumberWaiting() + 1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));						
						cb.await();						
					} catch (Exception e) {
						e.printStackTrace();
					}				
				}
			};
			service.execute(runnable);
		}
		service.shutdown();
	}
}

5.3 application scenarios

        For example, a large task, often need to allocate a lot of sub-tasks to perform, only when all the subtasks have completed execution time to perform the main task, this time, you can choose the CyclicBarrier.

For example: We need the national statistics service data. The database in which the provinces are independent, that is to say by provinces library. And a large amount of statistical data, statistical process is relatively slow. To improve performance, fast calculation. We take concurrent way, multiple threads simultaneously calculate provincial data, and finally summary statistics. Here is useful CyclicBarrier

package com.bjc.thread.demo6;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * 各省数据独立,分库存偖。为了提高计算性能,统计时采用每个省开一个线程先计算单省结果,最后汇总。
 * 
 * @author guangbo email:[email protected]
 * 
 */
public class TestDemo3 {

	// private ConcurrentHashMap result = new ConcurrentHashMap();

	public static void main(String[] args) {
		TotalService totalService = new TotalServiceImpl();
		CyclicBarrier barrier = new CyclicBarrier(5,
				new TotalTask(totalService));

		// 实际系统是查出所有省编码code的列表,然后循环,每个code生成一个线程。
		new BillTask(new BillServiceImpl(), barrier, "北京").start();
		new BillTask(new BillServiceImpl(), barrier, "上海").start();
		new BillTask(new BillServiceImpl(), barrier, "广西").start();
		new BillTask(new BillServiceImpl(), barrier, "四川").start();
		new BillTask(new BillServiceImpl(), barrier, "黑龙江").start();

	}
}

/**
 * 主任务:汇总任务
 */
class TotalTask implements Runnable {
	private TotalService totalService;

	TotalTask(TotalService totalService) {
		this.totalService = totalService;
	}

	public void run() {
		// 读取内存中各省的数据汇总,过程略。
		totalService.count();
		System.out.println("=======================================");
		System.out.println("开始全国汇总");
	}
}

/**
 * 子任务:计费任务
 */
class BillTask extends Thread {
	// 计费服务
	private BillService billService;
	private CyclicBarrier barrier;
	// 代码,按省代码分类,各省数据库独立。
	private String code;

	BillTask(BillService billService, CyclicBarrier barrier, String code) {
		this.billService = billService;
		this.barrier = barrier;
		this.code = code;
	}

	public void run() {
		System.out.println("开始计算--" + code + "省--数据!");
		billService.bill(code);
		// 把bill方法结果存入内存,如ConcurrentHashMap,vector等,代码略
		System.out.println(code + "省已经计算完成,并通知汇总Service!");
		try {
			// 通知barrier已经完成
			barrier.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (BrokenBarrierException e) {
			e.printStackTrace();
		}
	}

}

6. CountDownLatch synchronization tool (Counter)

6.1 Overview

        CountDownLatch is Java Concurrency tools introduced after Java1.5, on java.util.concurrent package below.

        CountDownLatch allows one or more threads wait for other threads to complete their work before execution; CountDownLatch JDK 5+ is a realization inside atresia. Popular appreciated that, if a CountDownLatch a countdown timer, call its methods when countDown, will counter is decremented when the count is equal to 0, then all or a single waiting waiting started.

note:

1. latch (Latch) concept: the progress of a synchronous method, the thread can be delayed until the thread reaches an end state. Popular talk is, a lockout is equivalent to a door, all threads are blocked before the doors opened, once the doors open all the threads will pass, but once the door is opened, all the threads are passed, then the lockout status on It fails, the state of the door will not be changed, can only be turned on. That lockout state is disposable, it ensures that all specific activities need to be completed before the open after the locking latch is opened.

2. countdownlatch is a synchronous type tools, does not involve the lock, when the count value of zero current thread continues to run, does not involve the synchronization only involves communicating the thread when it is more appropriate to use

6.2 API

Constructor:

        CountDownLatch (int count): number of counts specified, can only be set once

void countDown (): This method is called the count by 1

void await (): Calling this method has been blocking the current thread until the timer value is zero, unless the thread is interrupted.

Long getCount (): get the current count

boolean await (long timeout, TimeUnit unit): Calling this method has been blocking the current thread until the timer value is zero, unless the thread is interrupted or counter timeout, timeout, false on behalf of the counter.

E.g:

package com.bjc.thread.demo6;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountdownLatchTest {

	public static void main(String[] args) {
		ExecutorService service = Executors.newCachedThreadPool();
		// 创建命令,计数器初始值为1
		final CountDownLatch cdOrder = new CountDownLatch(1);
		// 创建响应,计数器初始值为3
		final CountDownLatch cdAnswer = new CountDownLatch(3);		
		for(int i=0;i<3;i++){
			Runnable runnable = new Runnable(){
					public void run(){
					try {
						System.out.println("线程" + Thread.currentThread().getName() + 
								"正准备接受命令");	
						// 等待命令计数器为0在执行
						cdOrder.await();
						System.out.println("线程" + Thread.currentThread().getName() + 
						"已接受命令");								
						Thread.sleep((long)(Math.random()*10000));	
						System.out.println("线程" + Thread.currentThread().getName() + 
								"回应命令处理结果");	
						// 响应计数器减1
						cdAnswer.countDown();						
					} catch (Exception e) {
						e.printStackTrace();
					}				
				}
			};
			service.execute(runnable);
		}		
		try {
			Thread.sleep((long)(Math.random()*10000));
		
			System.out.println("线程" + Thread.currentThread().getName() + 
					"即将发布命令");	
			// 命令计数器减1为0,开始执行
			cdOrder.countDown();
			System.out.println("线程" + Thread.currentThread().getName() + 
			"已发送命令,正在等待结果");	
			// 响应计数器开始等待直到计数器为0
			cdAnswer.await();
			System.out.println("线程" + Thread.currentThread().getName() + 
			"已收到所有响应结果");	
		} catch (Exception e) {
			e.printStackTrace();
		}				
		service.shutdown();
	}
}

operation result:

6.3 Application

1. Open the plurality of threads to download a large file block, each thread only download a fixed length, and finally by another thread for all the segments to splice

2. After the main thread and then execute the application responsible for starting the thread of hope in the framework of services has been launched in the framework of all the services

3. Make sure that a calculation will not be executed, until the desired resource is initialized

4. Operation Excel files

7. Exchanger synchronization tool (exchanger)

7.1 Introduction

        Exchanger can exchange data between two threads, only two threads, he does not support the interchange of data between threads more

7.2 The principle

        Exchanger provides a synchronization point, in this synchronization point two threads may exchange data with each other. These two threads to exchange data exchange method, if the first thread to execute exchange method, it would have been to wait for a second thread also performs exchange, when two threads have reached the synchronization point, these two threads can exchange data , this thread will be produced by the data is passed to the other side. So the focus using Exchanger is paired threads exchange () method, when a pair of thread synchronization point reached, it will exchange data. Therefore, the thread object tools are paired

7.3 Important API

String exchange (V x): for the exchange, the exchange started and waits for another thread calls exchange

String exchange (V x, long timeout, TimeUnit unit): for the exchange, the exchange started and waits for another thread calls the exchange, and setting the maximum waiting time, when the waiting time exceeds the timeout will stop waiting

E.g:

package com.bjc.thread.demo6;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExchangerTest {

	public static void main(String[] args) {
		ExecutorService service = Executors.newCachedThreadPool();
		// 定义交换者对象
		final Exchanger exchanger = new Exchanger();
		service.execute(new Runnable(){
			public void run() {
				try {				
					// 定义数据1
					String data1 = "张三";
					System.out.println("线程" + Thread.currentThread().getName() + 
					"正在把数据" + data1 +"换出去");
					Thread.sleep((long)(Math.random()*10000));
					// 交换-直到两个线程都执行了交换之后,程序才接着执行,否则一直等下去
					String data2 = (String)exchanger.exchange(data1);
					System.out.println("线程" + Thread.currentThread().getName() + 
					"换回的数据为" + data2);
				}catch(Exception e){
					
				}
			}	
		});
		service.execute(new Runnable(){
			public void run() {
				try {				
					// 定义数据2
					String data1 = "李四";
					System.out.println("线程" + Thread.currentThread().getName() + 
					"正在把数据" + data1 +"换出去");
					Thread.sleep((long)(Math.random()*10000));		
					// 交换-直到两个线程都执行了交换之后,程序才接着执行,否则一直等下去
					String data2 = (String)exchanger.exchange(data1);
					System.out.println("线程" + Thread.currentThread().getName() + 
					"换回的数据为" + data2);
				}catch(Exception e){
					
				}				
			}	
		});		
	}
}

operation result:

 

Published 128 original articles · won praise 6 · views 3229

Guess you like

Origin blog.csdn.net/weixin_43318134/article/details/103658196