首页 > 编程 > Java > 正文

java中的线程执行器总结!

2019-11-10 22:18:30
字体:
来源:转载
供稿:网友

当需要有大量线程运行时,不可避免的就要反复进行创建,运行,销毁线程,然而显式的这些操作本身都是比较消耗CPU的,必须很好的将这些线程管理起来,如线程池就是一个很好的例子,java提供了许多Executor用以提供对线程的管理。

1.ThreadPoolExecutor

下面程序模拟了利用ThreadPoolExetor来执行10个任务,

[java] view plain copy PRint?在CODE上查看代码片public class Program{      public static void main(String[] agrs){          Server s=new Server();          for(int i=0;i<10;i++){              Task task=new Task(new Date(),"task"+i);              s.executeTask(task);          }          s.endServer();      }  }    class Task implements Runnable{      private Date initDate;      private String name;      public Task(Date initDate,String name){          this.initDate=initDate;          this.name=name;      }      @Override      public void run(){          System.out.printf("%s: Task %s: Created on: %s/n",Thread.currentThread().getName(),name,initDate);      System.out.printf("%s: Task %s: Started on: %s/n",Thread.currentThread().getName(),name,new Date());      try {              Long duration=(long)(Math.random()*10);              System.out.printf("%s: Task %s: Doing a task during %d seconds/n",Thread.currentThread().getName(),name,duration);              TimeUnit.SECONDS.sleep(duration);              } catch (InterruptedException e) {              e.printStackTrace();          }          System.out.printf("%s: Task %s: Finished on: %s/n",Thread.currentThread().getName(),name,new Date());      }        }    class Server{      private ThreadPoolExecutor executor;      public Server(){          executor=(ThreadPoolExecutor)Executors.newCachedThreadPool();      }            public void executeTask(Task task){          System.out.println("a new task has arrived");          executor.execute(task);          System.out.printf("Server: Pool Size: %d  Active Count: %d  Completed Tasks: %d/n",executor.getPoolSize(),executor.getActiveCount(),executor.getCompletedTaskCount());      }      public void endServer(){          executor.shutdown();      }        }  执行结果如下:

a%20new%20task%20has%20arrivedpool-1-thread-1:%20Task%20task0:%20Created%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-1:%20Task%20task0:%20Started%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014Server:%20Pool%20Size:%201 %20Active%20Count:%201 %20Completed%20Tasks:%200pool-1-thread-1:%20Task%20task0:%20Doing%20a%20task%20during%204%20secondsa%20new%20task%20has%20arrivedServer:%20Pool%20Size:%202 %20Active%20Count:%201 %20Completed%20Tasks:%200a%20new%20task%20has%20arrivedpool-1-thread-2:%20Task%20task1:%20Created%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-2:%20Task%20task1:%20Started%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-3:%20Task%20task2:%20Created%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-3:%20Task%20task2:%20Started%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-3:%20Task%20task2:%20Doing%20a%20task%20during%201%20secondsServer:%20Pool%20Size:%203 %20Active%20Count:%202 %20Completed%20Tasks:%200a%20new%20task%20has%20arrivedpool-1-thread-2:%20Task%20task1:%20Doing%20a%20task%20during%203%20secondspool-1-thread-4:%20Task%20task3:%20Created%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-4:%20Task%20task3:%20Started%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-4:%20Task%20task3:%20Doing%20a%20task%20during%203%20secondsServer:%20Pool%20Size:%204 %20Active%20Count:%203 %20Completed%20Tasks:%200a%20new%20task%20has%20arrivedServer:%20Pool%20Size:%205 %20Active%20Count:%204 %20Completed%20Tasks:%200a%20new%20task%20has%20arrivedpool-1-thread-5:%20Task%20task4:%20Created%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-6:%20Task%20task5:%20Created%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-6:%20Task%20task5:%20Started%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-6:%20Task%20task5:%20Doing%20a%20task%20during%201%20secondsServer:%20Pool%20Size:%206 %20Active%20Count:%205 %20Completed%20Tasks:%200a%20new%20task%20has%20arrivedpool-1-thread-5:%20Task%20task4:%20Started%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-7:%20Task%20task6:%20Created%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-7:%20Task%20task6:%20Started%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014Server:%20Pool%20Size:%207 %20Active%20Count:%206 %20Completed%20Tasks:%200a%20new%20task%20has%20arrivedpool-1-thread-7:%20Task%20task6:%20Doing%20a%20task%20during%200%20secondspool-1-thread-5:%20Task%20task4:%20Doing%20a%20task%20during%206%20secondspool-1-thread-7:%20Task%20task6:%20Finished%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-8:%20Task%20task7:%20Created%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-8:%20Task%20task7:%20Started%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014Server:%20Pool%20Size:%208 %20Active%20Count:%207 %20Completed%20Tasks:%200pool-1-thread-8:%20Task%20task7:%20Doing%20a%20task%20during%202%20secondsa%20new%20task%20has%20arrivedpool-1-thread-7:%20Task%20task8:%20Created%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-7:%20Task%20task8:%20Started%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014Server:%20Pool%20Size:%208 %20Active%20Count:%207 %20Completed%20Tasks:%201a%20new%20task%20has%20arrivedpool-1-thread-7:%20Task%20task8:%20Doing%20a%20task%20during%206%20secondsServer:%20Pool%20Size:%209 %20Active%20Count:%208 %20Completed%20Tasks:%201pool-1-thread-9:%20Task%20task9:%20Created%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-9:%20Task%20task9:%20Started%20on:%20Wed%20Feb%2012%2014:54:12%20CST%202014pool-1-thread-9:%20Task%20task9:%20Doing%20a%20task%20during%208%20secondspool-1-thread-3:%20Task%20task2:%20Finished%20on:%20Wed%20Feb%2012%2014:54:13%20CST%202014pool-1-thread-6:%20Task%20task5:%20Finished%20on:%20Wed%20Feb%2012%2014:54:13%20CST%202014pool-1-thread-8:%20Task%20task7:%20Finished%20on:%20Wed%20Feb%2012%2014:54:14%20CST%202014pool-1-thread-2:%20Task%20task1:%20Finished%20on:%20Wed%20Feb%2012%2014:54:15%20CST%202014pool-1-thread-4:%20Task%20task3:%20Finished%20on:%20Wed%20Feb%2012%2014:54:15%20CST%202014pool-1-thread-1:%20Task%20task0:%20Finished%20on:%20Wed%20Feb%2012%2014:54:16%20CST%202014pool-1-thread-5:%20Task%20task4:%20Finished%20on:%20Wed%20Feb%2012%2014:54:18%20CST%202014pool-1-thread-7:%20Task%20task8:%20Finished%20on:%20Wed%20Feb%2012%2014:54:18%20CST%202014pool-1-thread-9:%20Task%20task9:%20Finished%20on:%20Wed%20Feb%2012%2014:54:20%20CST%202014

注意:

1.当将Runnable对象放入Executor里执行时,当执行完毕后记得要关闭执行器,不然执行器的永久运行将导致程序不会退出(非守护线程不结束,程序是不会结束的)。2.并不能因为执行器具有较好的线程管理能力而将大量的线程放入线程器里去执行,同样也会拖垮系统。所以在初始化时也可以指定执行器创建线程的容量,如

executor=(ThreadPoolExecutor)Executors.newFixedThreadPool(int%20number);

 

2.Callable %20 %20Callbale接口主要可以返回线程执行的结果,如当我们开辟多条线程去对数组进行排序时,假若每条线程执行的算法都不同,我们当然希望得到第一个排序完的时间(最优算法),或者我们需要知道每一个算法返回的时间,诸如此类的问题,都需要借助Callable,以下代码模拟了验证用户名和密码,随机返回结果,代码如下

[java] view%20plain copy print?public class Program{      public static void main(String[] agrs){          String username="fly";          String pwd="123456";          UserValidator v1=new UserValidator("v1");          UserValidator v2=new UserValidator("v2");          TaskValidator t1=new TaskValidator(v1,username,pwd);        TaskValidator t2=new TaskValidator(v2,username,pwd);      List<TaskValidator> taskList=new ArrayList<TaskValidator>();          taskList.add(t1);          taskList.add(t2);          ExecuteService es=(ExecuteService)Executors.newCachedThreadPool();          String result;          try {              result = executor.invokeAny(taskList);              System.out.printf("Main: Result: %s/n",result);              } catch (InterruptedException e) {              e.printStackTrace();              } catch (ExecutionException e) {              e.printStackTrace();              }              executor.shutdown();          }            }    class UserValidator{      private String name;      public UserValidator(String name){          this.name=name;      }            public boolean validate(String name,String pwd){          Random random=new Random();          try {                      long duration=(long)(Math.random()*10);                      System.out.printf("Validator %s: Validating a user during %d seconds/n",this.name,duration);                      TimeUnit.SECONDS.sleep(duration);                      } catch (InterruptedException e) {                      return false;                  }          return random.nextBoolean();      }            public String getName(){          return name;      }  }    class TaskValidator implements Callable<String>{      private UserValidator validator;      private String user;      private String pwd;      public TaskValidator(UserValidator validator,String user,String pwd ){          this.validator=validator;          this.user=user;          this.pwd=pwd;      }      @Override      public String call() throws Exception{          if (!validator.validate(user, passWord)) {              System.out.printf("%s: The user has not been found/n",validator.getName());              throw new Exception("Error validating user");          }          System.out.printf("%s: The user has been found/n",validator.getName());          return validator.getName();      }        }   %20 %20Callable实现的步骤其实和直接调用Executor没太大区别,唯一不同的就是,需要将所有的任务放入List列表里,而List的元素类型必须为“?%20extends%20Callable”,然后调用类似上面代码的invokeAny(这里是返回第一个任务的结果,还有其他方法,如invokeAll可以返回所有结果为一个集合)。

3.ScheduledThreadPoolExecutor %20 %20ScheduledThreadPoolExecutor可以延迟执行任务,下面程序开启5个任务,分别是1,2,3,4,5秒后自动启动,代码如下:

[java] view%20plain copy print?派生到我的代码片public class Program{      public static void main(String[] agrs){          ScheduledThreadPoolExecutor executor=(ScheduledThreadPoolExecutor)Executors.newScheduledThreadPool(1);          System.out.printf("Main: Starting at: %s/n",new Date());          for (int i=0; i<5; i++) {              Task task=new Task("Task "+i);              executor.schedule(task,i+1 , TimeUnit.SECONDS);          }          executor.shutdown();          try {              executor.awaitTermination(10, TimeUnit.SECONDS);              } catch (InterruptedException e) {              e.printStackTrace();          }          System.out.printf("Main: Ends at: %s/n",new Date());      }            }    class Task implements Callable<String>{      private String name;      public Task(String name){          this.name=name;      }      @Override      public String call() throws Exception{          System.out.printf("%s: Starting at : %s/n",name,new Date());          return "Hello, world";      }     }      ScheduledThreadPoolExecutor完成delay的效果主要靠,schedule(Callable<T> callable,long delay,TimeUnit t)这个函数完成的,第一个参数也可以是Runnable对象。而shutdown()只是通知虚拟机去关闭执行器,但是若发生任何异常则无法处理,所以需要利用awaitTerimination(long time,TimeUnit t)来等待所有任务完成。shutdown+awaitTermination算是一种优雅的关闭executor的方式了。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表