Multithreading (ii)

Source: Internet
Author: User

See Write a more detailed piece of description InvokeAll and Invokeany method, modify, and take to explain the problem.

Executorservice is a core interface provided by the JDK Concurrency Toolkit, which is equivalent to a thread pool that provides methods for performing tasks and managing the lifecycle. Most of the APIs in the Executorservice interface are relatively easy to use, this article mainly introduces the characteristics and use of the InvokeAll and Invokeany methods. Let's start with a few task classes: a time-consuming task, an exception task, and a short-term task. They will be used in the next Test code.

  1. package tasks;
  2. Import java.util.concurrent.Callable;
  3. Import Java.util.concurrent.TimeUnit;
  4. public class Sleepsecondscallable implements Callable<string>
  5. {
  6. private String name;
  7. private int seconds;
  8. Public sleepsecondscallable (String name, int seconds)
  9. {
  10. THIS.name = name;
  11. This.seconds = seconds;
  12. }
  13. Public String Call () throws Exception
  14. {
  15. SYSTEM.OUT.PRINTLN (name + ", begin to execute");
  16. Try
  17. {
  18. TimeUnit.SECONDS.sleep (SECONDS);
  19. } catch (Interruptedexception e)
  20. {
  21. SYSTEM.OUT.PRINTLN (name + "was disturbed during sleeping.");
  22. E.printstacktrace ();
  23. Return name + "_sleepsecondscallable_failed";
  24. }
  25. SYSTEM.OUT.PRINTLN (name + ", success to execute");
  26. Return name + "_sleepsecondscallable_succes";
  27. }
  28. }

This is a time-consuming task that simulates through sleep, which is an interruptible/terminated task that responds to an interrupt request.

[Java] view plaincopy

  1. package tasks;
  2. Import java.util.concurrent.Callable;
  3. public class Exceptioncallable implements Callable<string>
  4. {
  5. Private String name = NULL;
  6. Public exceptioncallable ()
  7. {
  8. }
  9. Public exceptioncallable (String name)
  10. {
  11. THIS.name = name;
  12. }
  13. @Override
  14. Public String Call () throws Exception
  15. {
  16. SYSTEM.OUT.PRINTLN ("Begin to Exceptioncallable.");
  17. System.out.println (Name.length ());
  18. System.out.println ("End to Exceptioncallable.");
  19. return name;
  20. }
  21. }

This is a task that may throw a null pointer exception during execution.

[Java] view plaincopy

  1. package tasks;
  2. Import Java.util.Random;
  3. Import java.util.concurrent.Callable;
  4. public class Randomtencharstask implements Callable<string>
  5. {
  6. @Override
  7. Public String Call () throws Exception
  8. {
  9. SYSTEM.OUT.PRINTLN ("Randomtencharstask begin to execute ...");
  10. StringBuffer content = new StringBuffer ();
  11. String base = "abcdefghijklmnopqrstuvwxyz0123456789";
  12. Random random = new random ();
  13. for (int i = 0; i <; i++)
  14. {
  15. int number = Random.nextint (Base.length ());
  16. Content.append (Base.charat (number));
  17. }
  18. System.out.println ("Randomtencharstask complete.result=" + content);
  19. return content.tostring ();
  20. }
  21. }

This is a normal short-term task that produces a string consisting of 10 random characters. 1. Test Invokeany ()

In the first case, submit 2 time-consuming tasks to the thread pool sleepsecondscallable

[Java] view plaincopy

    1. /**
    2. * Commits a task collection that terminates other unfinished tasks once a task is completed normally (without throwing an exception)
    3. /
    4. public static void Invokean Y1 () throws exception  
    5. {  
    6.     executorservice executorservice = Executors.newfixedthreadpool (3);  
    7.     list<callable<string >> tasks = new arraylist<callable<string>> ();  
    8.     Tas Ks.add (New sleepsecondscallable ("T1", 2));  
    9.     tasks.add (new Sleepsecondscallable ("T2", 1));  
    10.     String result = EXECUTORSERVICE.INV Okeany (Tasks);  
    11.     System.out.println ("result=" + result);   
    12.     executorservice.shutdown ();  

The result of the execution of the program is to return the execution result of the T2 thread t2_sleepsecondscallable_succes, while T1 throws Java.lang.InterruptedException:sleep interrupted.

the thread pool terminates other unfinished tasks once a task is completed normally (no exception is thrown during execution) .

In the second case, submit 3 exception tasks to the thread pool exceptioncallable

[Java] view plaincopy

  1. /**
  2. * No 1 normally completed tasks, Invokeany () method throws Executionexception, encapsulates the exception of elements in the task
  3. *
  4. */
  5. public static void InvokeAny2 () throws Exception
  6. {
  7. Executorservice Executorservice = Executors.newfixedthreadpool (3);
  8. list<callable<string>> tasks = new arraylist<callable<string>> ();
  9. Tasks.add (New exceptioncallable ());
  10. Tasks.add (New exceptioncallable ());
  11. Tasks.add (New exceptioncallable ());
  12. String result = Executorservice.invokeany (tasks);
  13. System.out.println ("result=" + result);
  14. Executorservice.shutdown ();
  15. }

Program execution result is: Call Invokeany () error java.util.concurrent.ExecutionException:java.lang.NullPointerException.

In other words: if there are no 1 tasks that are normally completed in the list of tasks submitted, then calling Invokeany will throw an exception, and it doesn't matter what task is thrown.

Third case: Commit 3 unusual tasks before committing 1 normal time-consuming tasks

[Java] view plaincopy

  1. /**
  2. * There are unusual tasks, normal tasks, Invokeany () will not throw an exception, return to the task of the first normal completion
  3. */
  4. public static void InvokeAny3 () throws Exception
  5. {
  6. Executorservice Executorservice = Executors.newfixedthreadpool (3);
  7. list<callable<string>> tasks = new arraylist<callable<string>> ();
  8. Tasks.add (New exceptioncallable ());
  9. Tasks.add (New exceptioncallable ());
  10. Tasks.add (New exceptioncallable ());
  11. Tasks.add (New exceptioncallable ());
  12. Tasks.add (New sleepsecondscallable ("T1", 2));
  13. String result = Executorservice.invokeany (tasks);
  14. System.out.println ("result=" + result);
  15. Executorservice.shutdown ();
  16. }

The result of the program execution is: No exception is thrown and the return result of the T2 task is printed out. Thatis, Invokeany () is independent of the order in which the tasks are submitted, but returns the task that was performed as early as normal .

In the fourth case, the test uses a limited-time version of the Invokeany (), the main function and the unlimited version of the difference is not small

[Java] view plaincopy

  1. /**
  2. * Not yet until timeout, so the task has been abnormally completed, thrown executionexception<br>
  3. * If the time expires before full, there is no unfinished task, throw TimeoutException
  4. */
  5. public static void Invokeanytimeout () throws Exception
  6. {
  7. Executorservice Executorservice = Executors.newfixedthreadpool (3);
  8. list<callable<string>> tasks = new arraylist<callable<string>> ();
  9. Tasks.add (New exceptioncallable ());
  10. Tasks.add (New exceptioncallable ());
  11. Tasks.add (New exceptioncallable ());
  12. Tasks.add (New exceptioncallable ());
  13. String result = Executorservice.invokeany (tasks, 2, timeunit.seconds);
  14. System.out.println ("result=" + result);
  15. Executorservice.shutdown ();
  16. }

The result of the program execution is: Throw executionexception. This is actually very reasonable, but also very well understood. If all the tasks are terminated abnormally before the time-out, then there is no need to wait, and if after a timeout there are still tasks running or waiting to run, then TimeoutException will be thrown.

Finally, let's look at the Executorservice.invokeany method signature and comment in the JDK source code.

[Java] view plaincopy

  1. /**
  2. * Executes the given tasks, returning the result
  3. * of one that has completed successfully (i.e., without throwing
  4. * An exception), if any do. Upon normal or exceptional return,
  5. * Tasks that has not completed is cancelled.
  6. * The results of this method is undefined if the given
  7. * Collection is modified while the this operation are in progress.
  8. *
  9. * @param tasks The collection of tasks
  10. * @return The result returned by one of the tasks
  11. * @throws interruptedexception if interrupted while waiting
  12. * @throws NullPointerException if tasks or any of its elements
  13. * Is <tt>null</tt>
  14. * @throws IllegalArgumentException if tasks is empty
  15. * @throws executionexception If no task successfully completes
  16. * @throws Rejectedexecutionexception If tasks cannot be scheduled
  17. * For execution
  18. */
  19. <T> T invokeany (collection<? extends callable<t>> tasks)
  20. Throws Interruptedexception, Executionexception;

Consistent with our test results, Invokeany () returns the immediate result of the task that was first completed (without throwing exception); The thread pool terminates running or waiting to run once a task is completed properly or an exception is called has not completed is cancelled) task. 2. Test InvokeAll () This method is relatively well understood, which is to perform all tasks in the Task list and return the futue corresponding to each task. That is, tasks do not interact with each other, and the future can be used to track the execution of each task, such as whether it is canceled, normal, or abnormal, mainly using the API provided by the future class.

[Java] view plaincopy

  1. public static void Testinvokeall () throws Exception
  2. {
  3. Executorservice Executorservice = Executors.newfixedthreadpool (5);
  4. list<callable<string>> tasks = new arraylist<callable<string>> ();
  5. Tasks.add (New sleepsecondscallable ("T1", 2));
  6. Tasks.add (New sleepsecondscallable ("T2", 2));
  7. Tasks.add (New Randomtencharstask ());
  8. Tasks.add (New exceptioncallable ());
  9. The thread that called the method blocks until all tasks are completed (normal completion/exception exit)
  10. list<future<string>> results = Executorservice.invokeall (tasks);
  11. All tasks in the task list are completed before the statement is executed
  12. System.out.println ("Wait for the result." + results.size ());
  13. Executorservice.shutdown ();
  14. for (future<string> f:results)
  15. {
  16. Iscanceled=false,isdone=true
  17. System.out.println ("iscanceled=" + f.iscancelled () + ", isdone="
  18. + F.isdone ());
  19. Exceptioncallable mission will be reported executionexception
  20. System.out.println ("task result=" + f.get ());
  21. }
  22. }

The execution results and some conclusions of the program have been written directly in the code comments. InvokeAll is a blocking method that waits for all tasks in the task list to complete. Future.isdone () always returns true regardless of whether the task is completed normally or terminated abnormally. The future.iscanceled () can be used to determine whether a task is canceled during execution. You can get the return result of a task through future.get (), or the exception that the task throws in execution.

In the second case, test the time-limited version of InvokeAll (COLLECTION<? extends callable<t>> tasks,long timeout, timeunit unit)

[Java] view plaincopy

  1. /**
  2. * Can be judged by future.iscanceled () whether the task is canceled or completed (normal/abnormal) <br>
  3. * Future.isdone () always returns True, no use for callers of InvokeAll ()
  4. */
  5. public static void Testinvokealltimeout () throws Exception
  6. {
  7. Executorservice Executorservice = Executors.newfixedthreadpool (5);
  8. list<callable<string>> tasks = new arraylist<callable<string>> ();
  9. Tasks.add (New sleepsecondscallable ("T1", 2));
  10. Tasks.add (New sleepsecondscallable ("T2", 2));
  11. Tasks.add (New sleepsecondscallable ("T3", 3));
  12. Tasks.add (New Randomtencharstask ());
  13. list<future<string>> results = Executorservice.invokeall (tasks, 1,
  14. Timeunit.seconds);
  15. System.out.println ("Wait for the result." + results.size ());
  16. for (future<string> f:results)
  17. {
  18. System.out.println ("iscanceled=" + f.iscancelled () + ", isdone="
  19. + F.isdone ());
  20. }
  21. Executorservice.shutdown ();
  22. }

The execution results are:

Wait for the Result.4
Iscanceled=true,isdone=true
Iscanceled=true,isdone=true
Iscanceled=true,isdone=true
Iscanceled=false,isdone=true

This means that a given time-out expires, a task that has not yet been completed is canceled, that is, future.iscancelled () returns True, and Future.iscancelled () returns false before the timeout period, whether it is a normal or abnormally terminated task.
In the third case, the thread is interrupted before the test waits for invokeall execution to complete.

[Java] view plaincopy

  1. /**
  2. * If the thread is interrupted while waiting for InvokeAll () execution to complete, it throws interruptedexception<br>
  3. * This time the thread pool terminates tasks that are not completed, mainly to reduce the waste of resources.
  4. */
  5. public static void Testinvokeallwheninterrupt () throws Exception
  6. {
  7. Final Executorservice Executorservice = Executors.newfixedthreadpool (5);
  8. Thread that calls InvokeAll
  9. Thread invokeallthread = new Thread () {
  10. @Override
  11. public void Run ()
  12. {
  13. list<callable<string>> tasks = new arraylist<callable<string>> ();
  14. Tasks.add (New sleepsecondscallable ("T1", 2));
  15. Tasks.add (New sleepsecondscallable ("T2", 2));
  16. Tasks.add (New Randomtencharstask ());
  17. The calling thread blocks until all tasks are completed (normal completion/exception exit)
  18. Try
  19. {
  20. list<future<string>> results = Executorservice
  21. . InvokeAll (tasks);
  22. System.out.println ("Wait for the result." + results.size ());
  23. } catch (Interruptedexception e)
  24. {
  25. System.out
  26. . println ("I was wait,but my thread was interrupted.");
  27. E.printstacktrace ();
  28. }
  29. }
  30. };
  31. Invokeallthread.start ();
  32. Thread.Sleep (200);
  33. Invokeallthread.interrupt ();
  34. Executorservice.shutdown ();
  35. }

The invokeallthread thread called Executorservice.invokeall () and Invokeallthread was interrupted by another thread while waiting for the task to complete. This time,

Executorservice.invokeall () throws Java.lang.InterruptedException, task T1 and T2 are terminated and thrown java.lang.InterruptedException:sleep Interrupted.

This means that once the Executorservice.invokeall () method produces an exception, a task that has not yet been completed in the thread pool is canceled.

Multithreading (ii)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.