When you check the java util.concurrent package , there are some utility classes provided , after removing lots of abstract classes which is useless for our users. we may notice couple of them are quite useful in our work. I will describle the most popular 4 utility classes here in this article;
CountDownLatch : this classes normally will be used to monitor some initializations , after some initializations , it will help to inform the main thread to continues to do its job. for example : in zookeeper, in the begining, web connection will be firstly established and some instances will be initialised then. Thus initialization will be done after connection is establised. So this behavious will be monitored and informed by CountDownLatch
final CountDownLatch countDown = new CountDownLatch(2);
Thread t1 = new Thread(new Runnable() { @Override public void run() { try { System.out.println("enter thread t1" + "waiting for other threa d to finish..."); countDown.await(); // wait & block here,because new CountDownLatch(2), so if ther e are 2 threads making countDown signal, this thread will
continues to go
System.out.println("t1 thread continues to go..."); } catch (InterruptedException e) { e.printStackTrace(); }}},"t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { try { System.out.println("t2 initialise..."); Thread.sleep(3000); // sleep System.out.println("t2 finishs init,inform t1 to continue..."); countDown.countDown(); // make a countdown signal } catch (InterruptedException e) { e.printStackTrace(); } }});
Thread t3 = new Thread(new Runnable() { @Override public void run() { try { System.out.println("t3 initialise..."); Thread.sleep(4000); System.out.println("t3 finish the init,inform t1 to continue.."); countDown.countDown(); // make a countdown signal } catch (InterruptedException e) { e.printStackTrace(); } } }); t1.start(); t2.start(); t3.start();
CyclicBarrier:Threads must all ready , then they can go , if any one thread is not ready. all other threads must wait for it .
static class Runner implements Runnable { private CyclicBarrier barrier; private String name; public Runner(CyclicBarrier barrier, String name) { this.barrier = barrier; this.name = name; } @Override public void run() { try { Thread.sleep(1000 * (new Random()).nextInt(5)); System.out.println(name + " ready OK."); barrier.await(); // wait,new CyclicBarrier(3),3 athletes must be
all ready = await() is called 3 times , } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println(name + " Go!!"); } } public static void main(String[] args) throws IOException, InterruptedException { CyclicBarrier barrier = new CyclicBarrier(3); // 3 athlets , called 3 times ExecutorService executor = Executors.newFixedThreadPool(3); executor.submit(new Thread(new Runner(barrier, "john"))); executor.submit(new Thread(new Runner(barrier, "peter"))); executor.submit(new Thread(new Runner(barrier, "luci"))); executor.shutdown(); }
Differences :
CountDownLatch is one thread waiting for other N threads information, then in the end one thread run
CyclicBarrier is multiple threads wait for one another and all run together in the end.
Semaphore : = ticket checker / bus conductor, which is used to limit the threads in high concurrency.
// thread pool ExecutorService exec = Executors.newCachedThreadPool(); // only allow 5 threads visit simoutanously final Semaphore semp = new Semaphore(5); // simulate 10 clients visit for (int index = 0; index < 20; index++) { final int NO = index; Runnable run = new Runnable() { public void run() { try { // acquire ticket,only 5 threads can be in,once there is a sl ot, then another thread can be let in ,limit the stream。 semp.acquire(); System.out.println("Accessing: " + NO); //simuate real business logic Thread.sleep((long) (Math.random() * 10000)); // after visit, release resource. semp.release(); } catch (InterruptedException e) { } } }; exec.execute(run); } try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } //System.out.println(semp.getQueueLength()); // exit thread pool exec.shutdown(); }
Future : used for a request waiting for response for a long time. so future will create a thread to fetch the data asyncronously and this dones't block the main thread to run. once future thread is finished, you can come back and check the data later.
private String para; public UseFuture(String para){ this.para = para; } /** * simulate real business logic, very time-consuming */ @Override public String call() throws Exception { //simulate a time consuming request Thread.sleep(5000); String result = this.para + "process finished"; return result; } //main method public static void main(String[] args) throws Exception { String queryStr = "query"; //FutureTask,pass in a business logic,this class implement Callable FutureTask<String> future = new FutureTask<String>(new UseFuture(queryStr)); FutureTask<String> future2 = new FutureTask<String>(new UseFuture(queryStr)); //create a thread pool ExecutorService executor = Executors.newFixedThreadPool(2); Future f1 = executor.submit(future); Future f2 = executor.submit(future2); System.out.println("request finished"); try { //this part can do the main business logic System.out.println("process real business logic..."); Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } //call and get the data,if call() hasn't finished,it will block and wait,
FutureTask is asyncronous。aaa will print first, future will print second System.out.println("data:" + future.get()); System.out.println("data:" + future2.get()); System.out.println("aaa"); executor.shutdown();
No comments:
Post a Comment