zoukankan      html  css  js  c++  java
  • Java创建线程的三种方式

    一、继承Thread类+重写run()方法

    启动:创建子类对象+对象.start();

    缺点:Java只支持单继承,如果我们的类已经从一个类继承,则无法再继承Thread类。

     1 package Thread;
     2 
     3 /**
     4  * 模拟龟兔赛跑
     5  * 1、创建多线程(方式一):继承 Thread + 重写run方法(线程体)
     6  * 2、使用线程:创建子类对象  + 对象.start()方法  线程启动
     7  */
     8 
     9 public class Demo01 {
    10 
    11     public static void main(String[] args) {
    12         //创建子类对象
    13         Rabbit rab = new Rabbit();
    14         Tortoise tor = new Tortoise();  
    15         //调用start方法 ,启动线程。 内部由CPU管控
    16         rab.start(); //不要调用run方法,由内部自己调用。
    17         tor.start();        
    18         for(int i=0;i<30;i++)
    19         {
    20             System.out.println("main-->"+i);                
    21         }
    22     }
    23 }
    24 
    25 class Rabbit extends Thread{
    26     //线程体  一切从run开始
    27     @Override
    28     public void run() {
    29         //线程体
    30         for(int i=0;i<30;i++)
    31         {
    32                 System.out.println("兔子跑了"+i+"步");               
    33         }
    34     }
    35 
    36 }
    37 
    38 class Tortoise extends Thread
    39 {
    40     @Override
    41     public void run() {
    42         //线程体
    43         for(int i=0;i<30;i++)
    44         {
    45                 System.out.println("乌龟跑了"+i+"步");               
    46         }
    47     }
    48 }

    二、实现Runnable接口+重写run方法

    启动:使用静态代理

    1、创建真实角色

    2、创建代理角色

    3、调用start()方法 启动线程

    优点:可以同时实现继承,Runnable接口方式更加通用一些

    1、避免单继承的局限性

    2、便于共享资源

    通过实现Runnable接口实现多线程(用到了静态代理设计模式)

     1 package Thread;
     2 
     3 /**
     4  * 推荐使用Runnable创建线程
     5  * 1、避免单继承的局限性
     6  * 2、便于共享资源
     7  */
     8 public class Demo03 {
     9     public static void main(String[] args) {
    10         //1)、创建真实角色
    11         Programmer pro = new Programmer();
    12         //2)、创建代理角色+真实角色引用
    13         Thread proxy = new Thread(pro);             
    14         //3)、调用start()方法 启动线程
    15         proxy.start();
    16 
    17         for(int i=0;i<100;i++){
    18             System.out.println("一边聊QQ");
    19         }
    20     }
    21 }
    22 
    23 /**
    24  * 使用Runnable 创建进程
    25  * 1、类实现Runable接口+重写run()方法
    26  * 2、启动多线程 使用静态代理
    27  *      1)、创建真实角色
    28  *      2)、创建代理角色
    29  *      3)、调用start()方法 启动线程
    30  */
    31 class Programmer implements Runnable{
    32     @Override
    33     public void run() {
    34         for(int i=0;i<100;i++){
    35             System.out.println("一边敲代码");
    36         }
    37     }
    38 }
    39 
    40 
    41 
    42 package Thread;
    43 
    44 /**
    45  * 抢票系统
    46  * 方便共享资源
    47  */
    48 public class Demo04 implements Runnable{
    49     private int num = 50;
    50     @Override
    51     public void run() {
    52         while(true){
    53             if(num<=0)
    54             {
    55                 break;//跳出循环
    56             }
    57             System.out.println(Thread.currentThread().getName()+"抢到了倒数第"+num--+"张。");           
    58         }
    59     }
    60 
    61     public static void main(String[] args) {
    62         //真实角色
    63         Demo04 web = new Demo04();
    64         //代理
    65         Thread t1 = new Thread(web,"德玛西亚");
    66         Thread t2 = new Thread(web,"卡特琳娜");
    67         Thread t3 = new Thread(web,"德邦总管");
    68 
    69         //启动线程
    70         t1.start();
    71         t2.start();
    72         t3.start();
    73     }
    74 }

    三、使用Callable接口创建多线程

    Callable和Future接口

    Callable是类似于Runnable的接口,实现*Callable接口的类和实现Runnable的类都是可被其它线程执行的任务*。

    优点:可以返回值,可以抛异常。

    缺点:繁琐。

    步骤:

    1、实现Callable接口+重写call方法

    2、借助执行调度服务ExecutorService获取Future对象

    ExecutorService ser = Executors.newFixedThreadPool(2);
    Future<Integer> result= ser.submit(tortoise);

    3、获取值result
    int num = result.get(); get方法返回值是一个泛型

    4、停止服务ser.shutdownNow();

    package Thread;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * 使用Callable接口方式创建多线程 
     */
    public class Demo05 {
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            //1、创建线程
            ExecutorService ser = Executors.newFixedThreadPool(2);//开两个线程
    
            Race tortoise = new Race("老乌龟",1000);
            Race rabbit = new Race("小兔子",500);
    
            //2、获取Future对象
            Future<Integer> result1 = ser.submit(tortoise);
            Future<Integer> result2 = ser.submit(rabbit);
    
            Thread.sleep(2000);//2秒
            tortoise.setFlag(false);//停止线程体循环 设置flag = false;
            rabbit.setFlag(false);
            //3、获取值
            int num1 = result1.get();
            int num2 = result2.get();
    
            System.out.println("乌龟跑了-->"+num1+"步");
            System.out.println("兔子跑了-->"+num2+"步");
            //4、停止服务
            ser.shutdownNow();
        }
    }
    
    class Race implements Callable<Integer>
    {
        private String name;//名称
        private long time;//延时时间
        private boolean flag = true;
        private int step = 0;//
    
        public Race() {
        }   
        public Race(String name) {
            super();
            this.name = name;
        }
        public Race(String name, int time) {
            super();
            this.name = name;
            this.time = time;
        }
    
        //有返回值了
        @Override
        public Integer call() throws Exception {
            while(flag){
                Thread.sleep(time);//延时
                step++;
            }
            return step;
        }
    
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public long getTime() {
            return time;
        }
        public void setTime(long  time) {
            this.time = time;
        }
        public boolean isFlag() {
            return flag;
        }
        public void setFlag(boolean flag) {
            this.flag = flag;
        }
        public int getStep() {
            return step;
        }
        public void setStep(int step) {
            this.step = step;
        }
    }

    运行结果:

    乌龟跑了-->3步
    兔子跑了-->5步

    四、Callable和Runnable不同点:
    (1)Callable规定的方法是call(),而Runnable规定的方法是run();

    2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的;

    (3)call()方法可抛出异常,而run()方法是不能抛出异常的;

    (4)运行Callable任务可拿到一个Future对象,Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果;

  • 相关阅读:
    Java中,&&与&,||与|的区别
    Hibernate中的merge方法 以及对象的几中状态
    你希望函数的某些参数强制使用关键字参数传递:
    7.1 可接受任意数量参数的函数:
    perl urlencode
    python UnicodeDecodeError: 'utf8' codec can't decode byte 0xd6 in position 15: invalid continuation
    python 使用__slots__
    python 面向对象编程
    Python flask post接口
    python flask get传参
  • 原文地址:https://www.cnblogs.com/luckyjcx/p/12268944.html
Copyright © 2011-2022 走看看