• 创建线程的三种方法详细对比


    1、继承Thread类:

        步骤:①、定义类继承Thread;

         ②、复写Thread类中的run方法;
        目的:将自定义代码存储在run方法,让线程运行
         ③、调用线程的start方法:
        该方法有两步:启动线程,调用run方法。
    复制代码
     1 public class ThreadDemo1 {
     2 
     3     public static void main(String[] args) {
     4         
     5         //创建两个线程
     6         ThreadDemo td = new ThreadDemo("zhangsan");
     7         ThreadDemo tt = new ThreadDemo("lisi");
     8         //执行多线程特有方法,如果使用td.run();也会执行,但会以单线程方式执行。
     9         td.start();
    10         tt.start();
    11         //主线程
    12         for (int i = 0; i < 5; i++) {
    13             System.out.println("main" + ":run" + i);
    14         }
    15     }
    16 }
    17 //继承Thread类
    18 class ThreadDemo extends Thread{
    19     
    20     //设置线程名称
    21     ThreadDemo(String name){
    22         super(name);
    23     }
    24     //重写run方法。
    25     public void run(){
    26         for(int i = 0; i < 5; i++){
    27         System.out.println(this.getName() + ":run" + i);  //currentThread()  获取当前线程对象(静态)。  getName() 获取线程名称。
    28         }
    29     }
    30 }
    复制代码

     2、实现Runnable接口: 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为run 的无参方法。

         实现步骤:  ①、定义类实现Runnable接口

              ②、覆盖Runnable接口中的run方法

                 将线程要运行的代码放在该run方法中。

              ③、通过Thread类建立线程对象。

              ④、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。

                 自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程执行指定对象的run方法就要先明确run方法所属对象

              ⑤、调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

    复制代码
    public class RunnableDemo {
        public static void main(String[] args) {
            RunTest rt = new RunTest();
            //建立线程对象
            Thread t1 = new Thread(rt);
            Thread t2 = new Thread(rt);
            //开启线程并调用run方法。
            t1.start();
            t2.start();
        }
    }
    
    //定义类实现Runnable接口
    class RunTest implements Runnable{
        private int tick = 10;
        //覆盖Runnable接口中的run方法,并将线程要运行的代码放在该run方法中。
        public void run(){
            while (true) {
                if(tick > 0){
                    System.out.println(Thread.currentThread().getName() + "..." + tick--);
                }
            }
        }
    }
    复制代码

     3、通过Callable和Future创建线程:

        实现步骤:①、创建Callable接口的实现类,并实现call()方法,改方法将作为线程执行体,且具有返回值。

             ②、创建Callable实现类的实例,使用FutrueTask类进行包装Callable对象,FutureTask对象封装了Callable对象的call()方法的返回值

             ③、使用FutureTask对象作为Thread对象启动新线程。

             ④、调用FutureTask对象的get()方法获取子线程执行结束后的返回值。

    复制代码
     1 public class CallableFutrueTest {
     2     public static void main(String[] args) {
     3         CallableTest ct = new CallableTest();                        //创建对象
     4         FutureTask<Integer> ft = new FutureTask<Integer>(ct);        //使用FutureTask包装CallableTest对象
     5         for(int i = 0; i < 100; i++){
     6             //输出主线程
     7             System.out.println(Thread.currentThread().getName() + "主线程的i为:" + i);
     8             //当主线程执行第30次之后开启子线程
     9             if(i == 30){        
    10                 Thread td = new Thread(ft,"子线程");
    11                 td.start();
    12             }
    13         }
    14         //获取并输出子线程call()方法的返回值
    15         try {
    16             System.out.println("子线程的返回值为" + ft.get());
    17         } catch (InterruptedException e) {
    18             e.printStackTrace();
    19         } catch (ExecutionException e) {
    20             e.printStackTrace();
    21         }
    22     }
    23 }
    24 class CallableTest implements Callable<Integer>{
    25     //复写call() 方法,call()方法具有返回值
    26     public Integer call() throws Exception {
    27         int i = 0;
    28         for( ; i<100; i++){
    29             System.out.println(Thread.currentThread().getName() + "的变量值为:" + i);
    30         }
    31         return i;
    32     }
    33 }
    复制代码

    三种方法对比:

        继承Thread:线程代码存放在Thread子类run方法中。

            优势:编写简单,可直接用this.getname()获取当前线程,不必使用Thread.currentThread()方法。

            劣势:已经继承了Thread类,无法再继承其他类。

        实现Runnable:线程代码存放在接口的子类的run方法中。

            优势:避免了单继承的局限性、多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。

            劣势:比较复杂、访问线程必须使用Thread.currentThread()方法、无返回值。

        实现Callable:

            优势:有返回值、避免了单继承的局限性、多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。

            劣势:比较复杂、访问线程必须使用Thread.currentThread()方法

    建议使用实现接口的方式创建多线程。

  • 相关阅读:
    [51单片机] TFT2.4彩屏1 [文字显示 画矩形]
    [51单片机] 中断1-中断整体介绍
    [汇编] 从键盘输入一个一位数字,然后响铃n声
    [汇编] 比较2个字符串是否相等
    [汇编] 将字符串里的一个'&'字符换成空格
    [汇编] 2数相加极简单版
    mysql的IFNULL函数
    mysql 中 unix_timestamp和from_unixtime函数
    Excel实现二级菜单联动
    Hibernate中@Embedded和@Embeddable注解
  • 原文地址:https://www.cnblogs.com/sx66/p/14308431.html
Copyright © 2020-2023  润新知