创建线程的方式

阅读:245

目录介绍

  • 01.创建线程的方式
  • 02.继承Thread类创建线程类
  • 03.通过Runnable接口创建线程类
  • 04.通过Callable和Future创建线程
  • 05.三种创建线程区别

02.继承Thread类创建线程类

  • 创建步骤如下
    • 定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。
    • 创建Thread子类的实例,即创建了线程对象。
    • 调用线程对象的start()方法来启动该线程。
  • 代码如下所示
    第一种方式的步骤:
    1: 定义一个类,让该类去继承Thread类
    2: 重写run方法
    3: 创建该类的对象
    4: 启动线程
    
    public class ThreadDemo {
    	public static void main(String[] args) {
    		// 创建对象
    		MyThread t1 = new MyThread() ;
    		MyThread t2 = new MyThread() ;
    		// 启动线程: 需要使用start方法启动线程, 如果我们在这里调用的是run方法,那么我们只是把该方法作为普通方法进行执行
    //		t1.run() ;
    //		t1.run() ;
    		t1.start() ;		// 告诉jvm开启一个线程调用run方法
    		// t1.start() ;		// 一个线程只能被启动一次
    		t2.start() ;
    		
    	}
    }
    
    public class MyThread extends Thread {
    	@Override
    	public void run() {
    		for(int x = 0 ; x < 1000 ; x++) {
    			System.out.println(x);
    		}
    	}
    }
    

03.通过Runnable接口创建线程类

  • 创建步骤如下
    • 定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
    • 创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
    • 调用线程对象的start()方法来启动该线程。
  • 代码如下所示
    实现多线程的第二中方式步骤:
    1: 定义一个类,让该类去实现Runnable接口
    2: 重写run方法
    3: 创建定义的类的对象
    4: 创建Thread的对象吧第三步创建的对象作为参数传递进来
    5: 启动线程
    
    public static void main(String[] args) {
    	// 创建定义的类的对象
    	MyThread mt = new MyThread() ;
    	// 创建Thread的对象吧第三步创建的对象作为参数传递进来
    	Thread t1 = new Thread(mt , "张三") ;
    	Thread t2 = new Thread(mt , "李四") ;
    	// 启动线程
    	t1.start() ;
    	t2.start() ;
    }
    
    public class MyThread implements Runnable {
    	@Override
    	public void run() {
    		for(int x = 0 ; x < 1000 ; x++) {
    			System.out.println(Thread.currentThread().getName() + "---" + x);
    		}
    		
    	}
    }
    

04.通过Callable和Future创建线程

  • Callable基础介绍
    • Runnable 从 JDK1.0 开始就有了,Callable 是在 JDK1.5 增加的。它们的主要区别是 Callable 的 call() 方法可以返回值和抛出异常,而 Runnable 的 run() 方法没有这些功能。Callable 可以返回装载有计算结果的 Future 对象。
    • 通过对比两个接口得到这样的结论
      • Callable 接口下的方法是 call(),Runnable 接口的方法是 run();
      • Callable 的任务执行后可返回值,而 Runnable 的任务是不能返回值的;
      • call() 方法可以抛出异常,run()方法不可以的;
      • 运行 Callable 任务可以拿到一个 Future 对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过 Future 对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果;
      public interface Runnable {
          public void run();
      }
      
      public interface Callable<V> {
          V call() throws Exception;
      }
      

  • 创建步骤如下所示
    • 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
    • 创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
    • 使用FutureTask对象作为Thread对象的target创建并启动新线程。
    • 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值,调用get()方法会阻塞线程。
  • 代码如下所示
    public class CallableThread implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            int i = 0;
            for (; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + " " + i);
            }
            return i;
        }
    }
    
    
    public class ThreadDemo {
        public static void main(String[] args) {
            CallableThread ctt = new CallableThread();
            FutureTask<Integer> ft = new FutureTask<>(ctt);
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + " 的循环变量i的值" + i);
                if (i == 20) {
                    new Thread(ft, "有返回值的线程").start();
                }
            }
            try {
                System.out.println("子线程的返回值:" + ft.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
    

05.三种创建线程区别

  • 采用实现Runnable、Callable接口的方式创见多线程时
    • 优势是:
      • 线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。
      • 在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
    • 劣势是:
      • 编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。
  • 使用继承Thread类的方式创建多线程时
    • 优势是:
      • 编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。
    • 劣势是:
      • 线程类已经继承了Thread类,所以不能再继承其他父类。


赞赏支持


精彩留言

发表评论