• 多线程基础(一)线程创建


    线程创建

    一. 线程创建的方式


    Ⅰ. 继承Thread类

    1. 自定义一个类,继承Thread类
    2. 重写run方法,run方法中用于定义当前线程的执行逻辑。
    3. 创建线程类的对象
    4. 开启线程 Thread类中start()方法启动线程
    /**
     * 此案例展示第一种创建线程之方法:继承Thread类
     * 说明:
     * 1.若 static 修饰 i,则共享i
     *
     * 关于Thread中的几个方法:
     * 1.虽然main()也是一个线程,但若需要Thread中的函数,如yiled()或sleep()
     * 也需要继承Thread,其本身不具有。
     * 2.在线程执行体中可以直接使用Thread中的方法如getName(),但main()中
     * 需要先返回当前线程对象。
     * 3.getName()是Thread类中的方法,若只是实现了Runnable接口,也需要先返回
     * 当前线程对象才能使用
     * 4.sleep() yiled()是Thread中的静态方法
     */
    
    public class FirstThread extends Thread {
        private int i;
        @Override
        public void run() {
            //继承了getName()
            for (;i<100; i++) {
                System.out.println(getName() + " " + i);
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            for(int i = 0;i<100;i++){
                System.out.println(Thread.currentThread().getName()+" "+i);
                if(i==20){
                    new FirstThread().start();
                    new FirstThread().start();
                    //yield();
                    sleep(1000);
                }
            }
        }
    }
    

    Ⅱ. 实现Runnable接口

    1. 自定义一个类 实现Runnable接口。
    2. 实现run方法。
    3. 创建一个自定义线程类的对象,但是该对象身上没有start启动线程的方法;可以创建Thread对象,将自定义线程类的对象作为参数传入构造方法中。
    4. 调用start方法启动线程
    /**
     * 此案例展示创建线程的第二种方法:实现Runnable接口
     * 其实现类仅作为Thread类的target。(把run()包装成一个Thread类)
     *
     * 说明:此方法中虽然new了两个类对象,但都作为了一个Thread类的target
     * 所以共享了变量i
     *
     */
    public class SecendThread implements Runnable {
        private int i;
        @Override
        public void run() {
            for(;i<100;i++){
                System.out.println(Thread.currentThread().getName()+" "+i);
            }
        }
    
        public static void main(String[] args) {
            for(int i = 0;i<100;i++){
                System.out.println(Thread.currentThread().getName()+" "+i);
                if(i==20){
                    SecendThread secendThread = new SecendThread();
                    new Thread(secendThread,"线程一").start();
                    new Thread(secendThread,"线程二").start();
                }
            }
        }
    }
    

    Ⅲ. 实现Runnable接口

    1. 自定义一个类 实现Callable接口
    2. 实现call方法 call方法中包含的是线程执行逻辑代码
    3. Executors获取线程服务对象
    4. 调用线程服务对象submit,将自定义线程对象传给submit方法的参数;submit返回值为Future类型,call方法的返回值就包含在Future对象中;可以通过future的get方法获取返回值对象
    public class ThreadDemo2 {
        public static void main(String[] args) throws Exception {
            //获取线程池的服务 对象
            ExecutorService service = Executors.newCachedThreadPool();
            MyThread2 myThread2 = new MyThread2();
            //通过submit方法来执行线程
            Future future = service.submit(myThread2);
            //Future中包含了线程的返回值
            Object o = future.get();
            System.out.println(o);
        }
    }
    
    //自定义线程--方式三
    class MyThread2 implements Callable{
        @Override
        public Object call() throws Exception {
            System.out.println("通过实现Callable接口自定义线程~~");
            return "hello";
        }
    }
    

    三. 对比总结


    1. 只有方法一需要继承Thread类,不如后两者。

    2. 只有方法三可以有返回值,可以抛出异常。

    3. Callable通过泛型来定义返回结果类型。在实际开发过程中和Runnable相似,如果需要执行结果那么使用Callable。

      Runnable Callable
      返回值 没有 通过泛型来定义返回值类型
      启动方式 1.通过Thread直接启动
      2.通过线程池的execute或者submit方法启动
      1.通过FutureTask转化成Runnable之后再通过Thread启动
      2.通过线程池的submit方法启动
      ⭐️异常处理 1.不允许抛异常,那么就无法通过全局方法来处理。
      允许抛异常,能通过全局方式来统一处理。
  • 相关阅读:
    微信小程序自定义分享图片
    rtop:一个通过 SSH 监控远程主机的交互式工具【转】
    mysql双主+keepalived【转】
    诡异的Linux磁盘空间被占用问题,根目录满了,df和du占用不一样【转】
    linux磁盘空间查看inode
    python数据库操作
    Jenkins 安装及使用
    编程入门python之定义函数【转】
    grep和sed匹配多个字符关键字的用法
    linux 如何删除文件夹下面的文件和文件夹,只保留两个文件
  • 原文地址:https://www.cnblogs.com/juzhuxiaozhu/p/13289879.html
Copyright © 2020-2023  润新知