zxyax

导航

Java多线程基础梳理

Java多线程基础梳理

Java给多线程编程提供了内置的支持。一条线程指的是进程中(正在运行的一个应用,包括操作系统分配的内存空间,一个或者多个线程)的一个单一顺序的控制流,一个进程中可以并发执行多个线程,没个线程并发的执行不同的任务。

多线程是多任务的一种特别的形式,但是多线程使用了更小的资源开销。

一个线程的生命周期

线程生命周期

  • 新建状态

    • 使用new关键字和Thread类或其子类建立一个线程对象后,该线程就处于新建状态。它保持这个状态直到程序start()这个线程。

  • 就绪状态

    • 当线程对象调用start()方法之后,该线程就处于就绪状态。就绪状态的线程处于就绪队列中,要等待JVM中线程调度器的调度。

  • 运行状态

    • 如果就绪状态的线程获取CPU资源,就可以执行run()方法,此时线程处于运行状态。

  • 阻塞状态

    • 如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:

      • 等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。

      • 同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。

      • 其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。

  • 死亡状态

    • 一个运行状态的线程完成任务或者其他终止条件触发时,该线程就切换为死亡状态。

如何创建一个线程

继承Thread类

创建线程的第一个方法就是继承Thread类,该类必须重写Thread中的run()方法,run()方法是新线程的入口点,调用的时候必须使用start方法才能够执行。

//创建TestThread01继承Thread类
//注意:线程开启之后不一定立即执行,线程执行由CPU统一调度
public class TestThread01 extends Thread{

   
   //重写run()方法
   @Override
   public  void run() {
       for (int i = 0; i < 10; i++) {
           System.out.println("");
      }
  }

   public static void main(String[] args) {
       
       //创建一个类对象(该类继承了Thread)
       TestThread01 testThread01 = new TestThread01();
       
       //调用start方法开启线程
       testThread01.start();
       for (int i = 0; i < 10; i++) {
           System.out.println("");
      }
  }
}

小结

  • 子类继承Thread类具备多线程能力

  • 启动线程:子类对象.start()

    • testThread01.start();

  • 不建议使用,避免OOP单继承局限性


实现Runnable接口

创建线程的第二个方法就是实现Runnable接口,该类也需要重写run()方法,将需要执行的线程放置到Runnable接口的实现类中,调用start()方法执行

//创建线程方式2.实现Runnable接口,重写run方法,执行线程需要丢入Runnable接口的实现类,调用start方法
public class TestThread02 implements Runnable{

   //重写run()方法
   @Override
   public void run() {
......
  }

   public static void main(String[] args) {
       //创建Runnable接口实现类对象
       TestThread02 testThread02 = new TestThread02();

       //创建线程对象,通过线程对象来开启我们的线程
       //new Thread(testThread02).start();
       Thread thread = new Thread(testThread02);
       thread.start();
  }
}

小结

  • 实现接口Runnable具有多线程能力

  • 启动线程:传入目标对象.Thread对象.start()

    • new Thread(目标对象).start();

  • 推荐使用,避免单继承局限性,灵活方便,方便同一个对象呗多个线程调用


通过Callable创建线程

1.实现Callable接口,需要返回值类型

2.重写call方法,需要抛出异常

3.创建目标对象

4.创建执行任务:ExecutorService ser = Executors.newFixedThreadPool(1);

5.提交执行:Future<Boolean> result = ser.submit(t1);

6.获取结果:boolean r1 = result.get()

7.关闭服务:ser.shutdown();

import java.util.concurrent.*;

//实现Callable方式创建线程
public class TestThread05 implements Callable<Boolean> {

   //重写call()方法
   @Override
   public Boolean call() throws Exception {
       return true;
  }

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

       //设置类对象
       TestThread05 testThread05 = new TestThread05();

       //创建执行任务,此处创建了1个线程
       ExecutorService service = Executors.newFixedThreadPool(1);

       //提交执行
       Future<Boolean> r1 = service.submit(testThread05);

       //获取结果
       boolean rs1 = r1.get();

       //关闭服务
       service.shutdownNow();
  }
}



posted on 2021-03-01 17:25  zxyax  阅读(20)  评论(0编辑  收藏  举报