java知识系列之线程

      工作总往往会遇到异步去执行某段逻辑,然后先处理其他事情, 处理完后再把那段逻辑的处理结果进行汇总的产景,这时候就需要使用线程了.

一个线程启动之后,是异步的去执行需要执行的内容的,不会影响主线程的流程,  往往需要让主线程指定后,等待子线程的完成. 这里有几种方式.

站在主线程的角度,我们可以分为主动式和被动式.

       主动式指主线主动去检测某个标志位, 判断子线程是否已经完成. 被动式指主线程被动的等待子线程的结束,很明显, 比较符合人们的胃口. 就是你事情做完了, 你告诉我,我汇总一下, 哈哈.那么主线程如何等待子线程工作完成呢.很简单, Thread类给我们提供了join系列的方法, 这些方法的目的就是等待当前线程的die.举个例子.

public class Threads {

 

     public static void main(String[] args) {

          SubThread thread = new SubThread();

          thread.start();

          //主线程处理其他工作,让子线程异步去执行.

          mainThreadOtherWork();

          System.out.println(“now waiting sub thread done.”);

          //主线程其他工作完毕,等待子线程的结束,调用join系列的方法即可(可以设置超时时间)

          try {

              thread.join();

          } catch (InterruptedException e) {

              e.printStackTrace();

          }

          System.out.println(“now all done.”);

     }

 

     private static void mainThreadOtherWork() {

          System.out.println(“main thread work start”);

          try {

              Thread.sleep(3000L);

          } catch (InterruptedException e) {

              e.printStackTrace();

          }

          System.out.println(“main thread work done.”);

     }

 

     public static class SubThread extends Thread{

          @Override

          public void run() {

              working();

          }

 

          private void working() {

              System.out.println(“sub thread start working.”);

              busy();

              System.out.println(“sub thread stop working.”);

          }

 

          private void busy() {

              try {

                   sleep(5000L);

              } catch (InterruptedException e) {

                   e.printStackTrace();

              }

          }

          

     }

}

 

本程序的数据有可能是如下:

1.       main thread work start

2.       sub thread start working.

3.       main thread work done.

4.       now waiting sub thread done.

5.       sub thread stop working.

6.       now all done.

忽略标号,当然输出也有可能是12调换位置了.这个我们是无法控制的.我们看下线程的join操作,究竟干了什么.

 

    public final void join() throws InterruptedException {

     join(0);

    }

这里是调用了

     public final synchronized void join(long millis) 

方法,参数为0, 表示没有超时时间, 等到线程结束为止. join(millis)方法里面有这么一段代码:

         while (isAlive()) {

          wait(0);

         }

说明,当线程处于活跃状态的时候,会一直等待, 直到这里的isAlive方法返回false,才会结束.isAlive方法是一个本地方法,他的作用是判断线程是否已经执行结束.注释是这么写的

Tests if this thread is alive. A thread is alive if it has been started and has not yet died.

 

可见, join系列方法可以帮助我们等待一个子线程的结束.

 

那么要问,有没有另外一种方法可以等待子线程结束?当然有的, 我们可以使用并发包下面的Future模式.

Future是一个任务执行的结果,他是一个将来时, 即一个任务执行, 立即异步返回一个Future对象,等到任务结束的时候, 会把值返回给这个future对象里面.我们可以使用ExecutorService接口来提交一个线程.

 

public class Threads {

 

     static ExecutorService executorService = Executors.newFixedThreadPool(1);

     

     @SuppressWarnings(“rawtypes”)

     public static void main(String[] args) throws InterruptedException, ExecutionException {

          SubThread thread = new SubThread();

//        thread.start();

          Future future = executorService.submit(thread);

          mainThreadOtherWork();

          System.out.println(“now waiting sub thread done.”);

          future.get();

//        try {

//            thread.join();

//        } catch (InterruptedException e) {

//            e.printStackTrace();

//        }

          System.out.println(“now all done.”);

          executorService.shutdown();

     }

 

     private static void mainThreadOtherWork() {

          System.out.println(“main thread work start”);

          try {

              Thread.sleep(3000L);

          } catch (InterruptedException e) {

              e.printStackTrace();

          }

          System.out.println(“main thread work done.”);

     }

 

     public static class SubThread extends Thread{

          @Override

          public void run() {

              working();

          }

 

          private void working() {

              System.out.println(“sub thread start working.”);

              busy();

              System.out.println(“sub thread stop working.”);

          }

 

          private void busy() {

              try {

                   sleep(5000L);

              } catch (InterruptedException e) {

                   e.printStackTrace();

              }

          }

          

     }

     

}

 

    这里, ThreadPoolExecutor是实现了 ExecutorService的方法, sumbit的过程就是把一个Runnable接口对象包装成一个 Callable接口对象,然后放到 workQueue里等待调度执行.当然, 执行的启动也是调用了threadstart来做到的,只不过这里被包装掉了.另外, 这里的thread是会被重复利用的,所以这里要退出主线程,需要执行以下shutdown方法以示退出使用线程池.扯远了

 

    这种方法是得益于Callable接口和Future模式,调用future接口的get方法,会同步等待该future执行结束,然后获取到结果. Callbale接口的接口方法是 V call();是可以有返回结果的, Runnable void run(),是没有返回结果的. 所以, 这里即使被包装成Callbale接口, future.get返回的结果也是null.如果需要得到返回结果,建议使用Callable接口.

 

    通过队列来控制线程的进度,是很好的一个理念. 我们完全可以自己搞个队列, 自己控制. 这样也可以实现.不信看代码:

 

public class Threads {

 

//   static ExecutorService executorService = Executors.newFixedThreadPool(1);

     static final BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1);

     public static void main(String[] argsthrows InterruptedException, ExecutionException {

          SubThread thread = new SubThread(queue);

          thread.start();

//        Future future = executorService.submit(thread);

          mainThreadOtherWork();

          System.out.println(“now waiting sub thread done.”);

//        future.get();

          queue.take();

//        try {

//            thread.join();

//        } catch (InterruptedException e) {

//            e.printStackTrace();

//        }

          System.out.println(“now all done.”);

//        executorService.shutdown();

     }

 

     private static void mainThreadOtherWork() {

          System.out.println(“main thread work start”);

          try {

              Thread.sleep(3000L);

          } catch (InterruptedException e) {

              e.printStackTrace();

          }

          System.out.println(“main thread work done.”);

     }

 

     public static class SubThread extends Thread{

          

          private BlockingQueue<Integer> queue;

          

          /**

           * @param queue

           */

          public SubThread(BlockingQueue<Integer> queue) {

              this.queue = queue;

          }

 

          @Override

          public void run() {

              try{

              working();

              }finally{

                   try {

                        queue.put(1);

                   } catch (InterruptedException e) {

                        e.printStackTrace();

                   }

              }

              

          }

 

          private void working() {

              System.out.println(“sub thread start working.”);

              busy();

              System.out.println(“sub thread stop working.”);

          }

 

          private void busy() {

              try {

                   sleep(5000L);

              } catch (InterruptedException e) {

                   e.printStackTrace();

              }

          }

          

     }

     

}

 

    这里是得益于我们用了一个阻塞队列,他的put操作和take操作都会阻塞(同步),在满足条件的情况下.当我们调用take()方法是,由于子线程还没结束, 队列是空的, 所以这里的take操作会阻塞,直到子线程结束的时候,往队列里面put了个元素,表明自己结束了. 这时候主线程的take()就会返回他拿到的数据.当然, 他拿到什么我们是不必去关心的.

以上几种情况都是针对子线程只有1个的时候.当子线程有多个的时候,情况就不妙了.

第一种方法,你要调用很多个线程的join,特别是当你的线程不是for循环创建的,而是一个一个创建的时候.

第二种方法,要调用很多的futureget方法,同第一种方法.

第三种方法,比较方便一些, 只需要每个线程都在queue里面 put一个元素就好了.但是,第三种方法, 这个队列里的对象, 对我们是毫无用处,我们为了使用队列, 而要不明不白浪费一些内存, 那有没有更好的办法呢?

有的, concurrency包里面提供了好多有用的东东,其中, CountDownLanch就是我们要用的.

CountDownLanch是一个倒数计数器, 给一个初始值(>=0), 然后没countDown一次就会减1,这很符合等待多个子线程结束的产景:一个线程结束的时候, countDown一次,直到所有都countDown ,那么所有子线程就都结束了.

先看看CountDownLanch有哪些方法:

await: 会阻塞等待计数器减少到0位置.带参数的await是多了等待时间.

countDown: 将当前的技术减1

getCount(): 返回当前的计数

显而易见,我们只需要在子线程执行之前,赋予初始化countDownLanch,并赋予线程数量为初始值.

每个线程执行完毕的时候,countDown一下.主线程只需要调用await方法,可以等待所有子线程执行结束,看代码:

 

public class Threads {

 

//   static ExecutorService executorService = Executors.newFixedThreadPool(1);

     static final BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1);

     public static void main(String[] argsthrows InterruptedException, ExecutionException {

          int threads = 5;

          CountDownLatch countDownLatch = new CountDownLatch(threads);

          for(int i=0;i<threads;i++){

              SubThread thread = new SubThread(2000*(i+1), countDownLatch);

              thread.start();

          }

//        Future future = executorService.submit(thread);

          mainThreadOtherWork();

          System.out.println(“now waiting sub thread done.”);

//        future.get();

//        queue.take();

          countDownLatch.await();

//        try {

//            thread.join();

//        } catch (InterruptedException e) {

//            e.printStackTrace();

//        }

          System.out.println(“now all done.”);

//        executorService.shutdown();

     }

 

     private static void mainThreadOtherWork() {

          System.out.println(“main thread work start”);

          try {

              Thread.sleep(3000L);

          } catch (InterruptedException e) {

              e.printStackTrace();

          }

          System.out.println(“main thread work done.”);

     }

 

     public static class SubThread extends Thread{

          

//        private BlockingQueue<Integer> queue;

          private CountDownLatch countDownLatch;

          private long work;

          

          /**

           * @param queue

           */

//        public SubThread(BlockingQueue<Integer> queue) {

//            this.queue = queue;

//            this.work = 5000L;

//        }

          

          public SubThread(long work, CountDownLatch countDownLatch) {

//            this.queue = queue;

              this.countDownLatch = countDownLatch;

              this.work = work;

          }

 

          @Override

          public void run() {

              try{

              working();

              }finally{

//                 try {

//                      queue.put(1);

//                 } catch (InterruptedException e) {

//                      e.printStackTrace();

//                 }

                   countDownLatch.countDown();

              }

              

          }

 

          private void working() {

              System.out.println(getName()+” sub thread start working.”);

              busy();

              System.out.println(getName()+” sub thread stop working.”);

          }

 

          private void busy() {

              try {

                   sleep(work);

              } catch (InterruptedException e) {

                   e.printStackTrace();

              }

          }

          

     }

}

      此种方法也适用于使用 ExecutorService summit的任务的执行.

      另外还有一个并发包的类CyclicBarrier,这个是()线程之间的互相等待的利器.栅栏, 就是把大家都在一个地方堵住, 就像水闸, 等大家都完成了之前的操作,在一起继续下面的操作.不过就不再本篇的讨论访问内了.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此微信小程序医院挂号预约系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。微信小程序医院挂号预约系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,医生信息管理,医院信息管理,科室信息管理,预约信息管理,预约取消管理,留言板,系统管理。微信小程序用户可以注册登录,查看医院信息,查看医生信息,查看公告资讯,在科室信息里面进行预约,也可以取消预约。微信小程序医院挂号预约系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值