java Thread学习(基础)

本文详细介绍了Java中线程的基本概念与实现方式,包括Runnable接口与Thread类的使用,以及如何利用ExecutorService管理线程。此外还探讨了如何通过Callable获取线程的返回值,并介绍了线程异常处理的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Thread学习

  1. 定义一个任务

    • 实现Runnable接口,重写run()方法。
    • 继承Thread类,重写run()方法。
      //extends Thread
      public class LiftOff extends Thread{
          protected int countDown = 10;
          private static int taskCount= 0;
          private final int id= taskCount++;
          public LiftOff() {}
          public LiftOff(int countDown) {
              this.countDown = countDown;
          }
          public String status() {
              return "#" + id + "(" + (countDown > 0 ? countDown : "Liftoff") + ").";
          }
          @Override
          public void run() {
              while(countDown-- > 0) {
                  System.out.println(status());
                  Thread.yield();//yield提示系统该任务重要的部分已经完成,可以进行切换线程。
              }
          }
      }
    //implements Runnable
    public class LiftOff implements Runnable{
        protected int countDown = 10;
        private static int taskCount= 0;
        private final int id= taskCount++;
        public LiftOff() {}
        public LiftOff(int countDown) {
            this.countDown = countDown;
        }
        public String status() {
            return "#" + id + "(" + (countDown > 0 ? countDown : "Liftoff") + ").";
        }
        @Override
        public void run() {
            while(countDown-- > 0) {
                System.out.println(status());
                Thread.yield();
            }
        }
    }
  2. 创建一个线程 Thread

    使用Thread创建一个线程,构造器需要一个实现run()方法的对象

    public class MoreBasicThreads {
        public static void main(String[] args) {
            Thread thread1 = new Thread(new LiftOff());
            Thread thread2 = new Thread(new LiftOff());
            thread1.start();
            thread2.start();
            System.out.println("****");
        }
    }
  3. 使用Executor
    java.util.concurrent中提供了执行器(Executor)用于管理Thread对象。暴露了要执行的单一单元ExecutorService,用来构建执行线程。使用静态方法Executors来获取ExecutorService对象。

    ExecutorService种类:

    • CachedThreadPool:每次有线程时创建新的线程。
    • FixedThreadPool:一次性进行线程分配。可以节约时间。多个任务申请时,维护一个队列。
    • SingleThreadPool:指定为一个线程的FixedThreadPool,多个任务申请时,维护一个队列,逐个执行。所有任务使用相同的线程。

    Example:

    public class CachedThreadPool {
        public static void main(String[] args) {
            ExecutorService service = Executors.newCachedThreadPool();//获取ExecutorService对象
            for(int i = 0; i < 5; i++) {
                service.execute(new LiftOff());//execute(Runnable)创建线程
            }
            service.shutdown();//不在接受新的线程
            System.out.println("***");
        }
    }
  4. 获取返回值 Callable
    实现Callable接口,Callable是一个泛型接口,指定返回值得类型。在Callable中方法call()用来执行任务并返回值。

    class TaskWithResult implements Callable<String> {
        private int id;
        public TaskWithResult(int id) {
            this.id = id;
        }
        @Override
        public String call() throws Exception {
            return "result to TaskWithResult " + id;
        }
    }
    public class CallableDemo {
        public static void main(String[] args) {
            ExecutorService service = Executors.newCachedThreadPool();
            ArrayList<Future<String>> results = new ArrayList<Future<String>>();//Callable<T>返回Future<T>类型
            for(int i = 0; i < 5; i++) {
                results.add(service.submit(new TaskWithResult(i)));//使用submit进行创建线程
            }
            for(Future<String> result : results) {
                System.out.println(result.isDone());//使用isDone()检测结果是否已经返回
                try{
                    System.out.println(result.get());//通过get()获取返回值。如果值没用,就会堵塞,知道结果准备好。也可以使用带有超时的get
                } catch(Exception e) {
                    e.printStackTrace();
                } finally {
                    System.out.println(result.isDone());
                }
            }
        }
    }
  5. 捕获异常
    异常在线程间不能传递,也就是说在线程内必须处理完线程的异常。
    Thread.UncaughtExceptionHandler是Java SE5提供的新接口,当一个线程因为未处理的异常导致崩溃时,会调用Thread.UncaughtExceptionHandler.uncaughtException()方法用来处理。

    继承Thread.UncaughtExceptionHandler接口,实现uncaughtException方法。然后在线程中通过setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler)方法注册在线程中就可以完成处理异常了

    class ExceptionThread2 implements Runnable{
        public void run() {
            Thread t = Thread.currentThread();//获取当前的线程
            System.out.println("run() by " + t);
            System.out.println("en = " + t.getUncaughtExceptionHandler());
            throw new RuntimeException();
        }
    }
    class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{
        //实现Thread.UncaughtExceptionHandler接口,重写uncaughtException方法     
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println("caught " + e);
        }
    }
    class HandlerThreadFactory implements ThreadFactory {
        //继承ThreadFactory接口,实现newThread(Runnable)接口,返回Thread
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            System.out.println("created " + thread);
            thread.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
            //setUncaughtExceptionHandler设置异常处理
            System.out.println("en = " + thread.getUncaughtExceptionHandler());
            return thread;
        }
    }
    public class CaptureUncaughtException {
        public static void main(String[] args) {
            ExecutorService service = Executors.newCachedThreadPool(new HandlerThreadFactory());
            service.execute(new ExceptionThread2());
        }
    }

常用方法

方法含义
Threadsleep(s)休息毫秒,可能会返回InterruptedException,线程之间不会传递异常,所以需要在线程内解决产生的异常
Threadyield()提示系统该任务重要的部分已经完成,可以进行切换线程。
ThreadcurrentThread()获取当前线程
ThreadsetPriority(x)设置线程的优先级
ThreadsetDaemon()设置为后台线程,后台线程时一种提供服务的线程。非后台线程结束时程序就会结束
ThreadisDaemon()判断是否是后台线程
Threadjoin()自身挂起,等待调用线程结束后再执行。也可以设置超时时间

PS:

  1. ExecutorService会创建一个ThreadFactory对象,用来创建线程
  2. 构造器中启动线程,可能会导致线程另一个任务访问了不稳定状态的对象
  3. 异常不会跨线程传递,所以线程内要处理自身的异常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值