java线程总结-1

来源:互联网 发布:淘宝联盟定向推广理由 编辑:程序博客网 时间:2024/06/05 14:39

    既然是学习线程,那就免不了要学习进程。很多人都会问这么一个问题进程和线程的区别。 做个小总结:

    1:进程是应用程序在操作系统中一次执行过程,而线程是进程的一部分必须依附于进程进行,可以说是进程的一个分支

     2:进程之间不会互相影响,一个进程挂了,另一个进程还可以继续进行。但是一个进程下,假如有20个线程,挂一个,其他19个都挂了,所以进程更加健壮

     3:进程虽然更加健壮,但是维护一个进程消耗的cpu也大,所以线程执行的程序往往效率更高,同时线程也是cpu能够调度的最小单位。

  根据以上的区别,我们应该考虑一个问题什么时候适合用多进程,什么时候适合用多线程。

  举2个例子:1 视频上传 2 数据库连接

    对于视频上传非常重要,的一点是这个对于健壮性要求非常高,如果同时多人上传视频,肯定是选择多进程;对于数据库连接,这个是会频繁地切换,创建。所以数据库连接就更适合多线程。

    销毁。如果使用进程开销太大,所以适合用多线程。

   进程实现方式

    (1)使用Runtime的exec()方法 
   (2)使用ProcessBuilder的start()方法

    这边就不详细介绍进程了,主要是总结java线程。

    1:线程的生命周期

   线程的生命周期有5种状态: 新建状态,就绪状态,运行状态,阻塞状态,销毁状态。

   以java的Thread来进行说明:Thread t = new Thread(new Runnable(){...});//新建状态

                                            t.start();//就绪状态

                                            jvm调用线程run方法//运行状态

                                           t.wait()或者t.sleep(1000)//阻塞状态

                                           run方法执行结束,stop,destroy//线程销毁

 
    2:java创建线程的方式

    java提供了三种创建线程的方式:

    1 继承Thread类本身

    2 实现Runnable接口

    3 通过Callable和Future创建线程

     第一种和第二种都非常常见和简单,就不总结了,着重说一下第三种:通过Callable和Future创建线程。

     public class CallableThread implements Callable<Integer>{

     public Integer call(){

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

                 //从currentThread().getName()可以知道多线程在同一时间其实只有一个线程在执行,这里用了一种调度算法频繁的调换

                //时间片轮转法、优先级调度法、多级反馈队列调度法等

                 System.out.println(Thread.currentThread().getName());

         } 

     }

     public static void main(String[] args){

        CallableThread ct = new CallableThread();

        FutureTask<Integer> ft = new FutureTask<Integer>(ct);

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

          new Thread(ft).start();

      }

        try{

         System.out.println(ft.get());

       }catch(Exception e){

                 e.printStrackTrace();

      }

      }

    }

    这里加入一个个人的理解,100个Thread用的都是同一个FutureTask对象,其实同一时间也只有一个线程对这个对象操作。关键要知道FutureTask能当作Thread

    的参数,但是实现Callable()接口的类的对象是不行的。FutureTask起到了中间桥梁的作用。

  3:线程的join()方法

   这里着重提一下join方法,作用是让2个交替执行的方法,能够顺序执行。

  4:java concurrent 包的使用

     在java5之后引入了concurrent包,让java的并发编程变得更加简单,下面着重介绍一下这个包的使用。

    ExecutorService service = Executors.newFixedThreadPool(5);

    service1会创建固定长度的线程池,当超过长度时会在一个线程队列中进行等待。

    ExecutorService service2 = Executors.newCachedThreadPool();

    service2是一种可以缓存的线程池,假如有线程处于空闲状态,会去调用空闲状态的线程池。如果没有就创建新的线程去处理。

    ExecutorService service3 = Executors.newShueduledThreadPool();

    service3顾名思义支持定时的任务

    ExecutorService service4 = Executors.newSingleThreadPool();

    service4线程池会将放入的任务顺序执行,并且如果任务失败会自动新建线程继续完成,健壮性很好,当然1,2都有这种功能。

    介绍完了线程,说一下submit和execute的区别

    1:2个方法接受的参数不一样

     submit接受实现了Callable接口的类,execute接受的是实现Runnale接口的类。

     这边顺便说一下FutureTask和Future的区别:Future是对于具体的线程的控制的一个类,比如说一个线程的执行结果就可以存在里面。是对具体任务进行

     控制的类,比如future.get().就是获得任务执行的结果。还有cancel(),isCancel()等方法

     而FutureTask是实现了RunnaleFutue接口的,也就是说FutureTask实现了Future接口的同时还是先了Runnable接口。

    具体使用Future fu = service.submit(ca);

                 service.submit(new FutureTask(ca));

    FutureTask类更加强大。

    最后讲一下ThreadLocal的使用

   ThreadLocal为每一个线程提供了一个全局变量,采用了空间换时间的方式来实现线程安全。

    通过get和set方法来设置和取值。

   

0 0
原创粉丝点击