Java创建线程的几种方式

继承Thread类

  1. 定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。
  2. 创建Thread子类的实例,即创建了线程对象。
  3. 调用线程对象的start()方法来启动该线程。
/** @author Strive */
public class CreatThreadDemo1 extends Thread {
  /** 构造方法: 继承父类方法的Thread(String name) */
  public CreatThreadDemo1(String name) {
    super(name);
  }

  @Override
  public void run() {
    if (!interrupted()) {
      for (int i = 1; i <= 10; i++) {
        System.out.println(getName() + "跑了" + i + "米");
        try {
          Thread.sleep(200);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }

  public static void main(String[] args) {
    CreatThreadDemo1 turtle = new CreatThreadDemo1("龟");
    CreatThreadDemo1 rabbit = new CreatThreadDemo1("兔");
    turtle.start();
    rabbit.start();

    // 中断第一个线程
    rabbit.interrupt();
  }
}

小贴士

  1. getName():返回调用该方法的线程的名;

  2. Thread.sleep(200):线程休息200ms;

  3. interrupt():中断线程。终止线程不允许用stop方法,该方法不会施放占用的资源。所以我们在设计程序的时候,要按照中断线程的思维去设计,就像上

    面的代码一样;

实现Runnable接口

  1. 定义 Runnable 接口的实现类,并重写该接口的 run() 方法,该 run() 方法的方法体同样是该线程的线程执行体;
  2. 创建 Runnable 实现类的实例,并依此实例作为 Thread 的 target 来创建 Thread 对象,该 Thread 对象才是真正的线程对象;
  3. 调用线程对象的 start() 方法来启动该线程;
/** @author Strive */
public class CreatThreadDemo2 implements Runnable {

  @Override
  public void run() {
    for (int i = 1; i <= 10; i++) {
      System.out.println(Thread.currentThread().getName() + "跑了" + i + "米");
      try {
        Thread.sleep(200);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }

  public static void main(String[] args) {
    // 将线程任务传给线程对象
    Thread turtle = new Thread(new CreatThreadDemo2());
    turtle.setName("龟");
    Thread rabbit = new Thread(new CreatThreadDemo2());
    rabbit.setName("兔");
    // 启动线程
    turtle.start();
    rabbit.start();
  }
}

匿名内部类创建线程对象

/** @author Strive */
@SuppressWarnings("all")
public class CreatThreadDemo3 extends Thread {
  public static void main(String[] args) {
    // 创建无参线程对象
    new Thread() {
      @Override
      public void run() {
        System.out.println("无参线程对象 - 线程执行了...");
      }
    }.start();
    // 创建带线程任务的线程对象
    new Thread(
            new Runnable() {
              @Override
              public void run() {
                System.out.println("带线程任务的线程对象 - 线程执行了...");
              }
            })
        .start();
    // 创建带线程任务并且重写run方法的线程对象
    new Thread(
        new Runnable() {
          @Override
          public void run() {
            System.out.println("runnable run 线程执行了...");
          }
        }) {
      @Override
      public void run() {
        System.out.println("override run 线程执行了...");
      }
    }.start();
  }
}

小贴士

创建带线程任务并且重写 run 方法的线程对象中,为什么只运行了 Thread 的 run 方法?因为 Thread 实现了 Runnable 接口,而 Runnable 接口里有一个 run 方法。所以,我们最终调用的重写的方法应该是 Thread 类的 run 方法。而不是 Runnable 接口的 run 方法。

创建带返回值的线程

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

/** @author Strive */
@SuppressWarnings("all")
public class CreatThreadDemo4 implements Callable {
  public static void main(String[] args) throws Exception {
    CreatThreadDemo4 demo4 = new CreatThreadDemo4();
    FutureTask<Integer> task = new FutureTask<Integer>(demo4);

    // FutureTask最 终实现的是runnable接口
    Thread thread = new Thread(task);
    thread.start();
    System.out.println("我可以在这里做点别的业务逻辑...因为FutureTask是提前完成任务");

    // 拿出线程执行的返回值
    Integer result = task.get();
    System.out.println("线程中运算的结果为:" + result);
  }

  /**
   * 重写Callable接口的call方法
   *
   * @throws Exception
   */
  @Override
  public Object call() throws Exception {
    System.out.println("业务逻辑计算中...");
    Thread.sleep(3000);
    return 1 + 1;
  }
}

Callable 接口

返回指定泛型的 call 方法。然后调用 FutureTask 对象的 get 方法得道 call 方法的返回值。
这其实是很有用的一个特性,因为多线程相比单线程更难、更复杂的一个重要原因就是因为多线程充满着未知性,某条线程是否执行了?某条线程执行了多久?某条线程执行的时候我们期望的数据是否已经赋值完毕?无法得知,我们能做的只是等待这条多线程的任务执行完毕而已。
而Callable+Future/FutureTask却可以获取多线程运行的结果,可以在等待时间太长没获取到需要的数据的情况下取消该线程的任务,真的是非常有用。

package java.util.concurrent;

/**
 * ..........
 * @since 1.5
 * @author Doug Lea
 * @param <V> the result type of method {@code call}
 */
@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

定时器Timer

import java.util.Timer;
import java.util.TimerTask;

/** @author Strive */
@SuppressWarnings("all")
public class CreatThreadDemo5 {
  public static void main(String[] args) {
    Timer timer = new Timer();
    timer.schedule(
        new TimerTask() {
          @Override
          public void run() {
            System.out.println("定时器线程执行了...");
          }
        },
        0,
        1000);
    // 延迟0,周期1s
  }
}

线程池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/** @author Strive */
@SuppressWarnings("all")
public class CreatThreadDemo6 {
  public static void main(String[] args) {
    // 创建一个具有10个线程的线程池
    ExecutorService threadPool = Executors.newFixedThreadPool(10);

    for (int i = 0; i < 10; i++) {
      threadPool.execute(
          new Runnable() {
            @Override
            public void run() {
              System.out.println(Thread.currentThread().getName() + "线程执行了...");
            }
          });
    }

    // 销毁线程池
    threadPool.shutdown();
  }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Strive_MY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值